<commit_before>/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#include "qwt_point_data.h"
#include "qwt_math.h"
#include <string.h>

/*!
  Constructor

  \param x Array of x values
  \param y Array of y values

  \sa QwtPlotCurve::setData(), QwtPlotCurve::setSamples()
*/
QwtPointArrayData::QwtPointArrayData(
        const QVector<double> &x, const QVector<double> &y ):
    d_x( x ),
    d_y( y )
{
}

/*!
  Constructor

  \param x Array of x values
  \param y Array of y values
  \param size Size of the x and y arrays
  \sa QwtPlotCurve::setData(), QwtPlotCurve::setSamples()
*/
QwtPointArrayData::QwtPointArrayData( const double *x,
        const double *y, size_t size )
{
    d_x.resize( static_cast<int>(size) );
    ::memcpy( d_x.data(), x, size * sizeof( double ) );

	d_y.resize(static_cast<int>(size));
    ::memcpy( d_y.data(), y, size * sizeof( double ) );
}

/*!
  \brief Calculate the bounding rectangle

  The bounding rectangle is calculated once by iterating over all
  points and is stored for all following requests.

  \return Bounding rectangle
*/
QRectF QwtPointArrayData::boundingRect() const
{
    if ( d_boundingRect.width() < 0 )
        d_boundingRect = qwtBoundingRect( *this );

    return d_boundingRect;
}

//! \return Size of the data set
size_t QwtPointArrayData::size() const
{
    return qMin( d_x.size(), d_y.size() );
}

/*!
  Return the sample at position i

  \param index Index
  \return Sample at position i
*/
QPointF QwtPointArrayData::sample( size_t index ) const
{
    return QPointF( d_x[int( index )], d_y[int( index )] );
}

//! \return Array of the x-values
const QVector<double> &QwtPointArrayData::xData() const
{
    return d_x;
}

//! \return Array of the y-values
const QVector<double> &QwtPointArrayData::yData() const
{
    return d_y;
}

/*!
  Constructor

  \param x Array of x values
  \param y Array of y values
  \param size Size of the x and y arrays

  \warning The programmer must assure that the memory blocks referenced
           by the pointers remain valid during the lifetime of the
           QwtPlotCPointer object.

  \sa QwtPlotCurve::setData(), QwtPlotCurve::setRawSamples()
*/
QwtCPointerData::QwtCPointerData(
        const double *x, const double *y, size_t size ):
    d_x( x ),
    d_y( y ),
    d_size( size )
{
}

/*!
  \brief Calculate the bounding rectangle

  The bounding rectangle is calculated once by iterating over all
  points and is stored for all following requests.

  \return Bounding rectangle
*/
QRectF QwtCPointerData::boundingRect() const
{
    if ( d_boundingRect.width() < 0 )
        d_boundingRect = qwtBoundingRect( *this );

    return d_boundingRect;
}

//! \return Size of the data set
size_t QwtCPointerData::size() const
{
    return d_size;
}

/*!
  Return the sample at position i

  \param index Index
  \return Sample at position i
*/
QPointF QwtCPointerData::sample( size_t index ) const
{
    return QPointF( d_x[int( index )], d_y[int( index )] );
}

//! \return Array of the x-values
const double *QwtCPointerData::xData() const
{
    return d_x;
}

//! \return Array of the y-values
const double *QwtCPointerData::yData() const
{
    return d_y;
}

/*!
   Constructor

   \param size Number of points
   \param interval Bounding interval for the points

   \sa setInterval(), setSize()
*/
QwtSyntheticPointData::QwtSyntheticPointData(
        size_t size, const QwtInterval &interval ):
    d_size( size ),
    d_interval( interval )
{
}

/*!
  Change the number of points

  \param size Number of points
  \sa size(), setInterval()
*/
void QwtSyntheticPointData::setSize( size_t size )
{
    d_size = size;
}

/*!
  \return Number of points
  \sa setSize(), interval()
*/
size_t QwtSyntheticPointData::size() const
{
    return d_size;
}

/*!
   Set the bounding interval

   \param interval Interval
   \sa interval(), setSize()
*/
void QwtSyntheticPointData::setInterval( const QwtInterval &interval )
{
    d_interval = interval.normalized();
}

/*!
   \return Bounding interval
   \sa setInterval(), size()
*/
QwtInterval QwtSyntheticPointData::interval() const
{
    return d_interval;
}

/*!
   Set a the "rectangle of interest"

   QwtPlotSeriesItem defines the current area of the plot canvas
   as "rect of interest" ( QwtPlotSeriesItem::updateScaleDiv() ).

   If interval().isValid() == false the x values are calculated
   in the interval rect.left() -> rect.right().

   \sa rectOfInterest()
*/
void QwtSyntheticPointData::setRectOfInterest( const QRectF &rect )
{
    d_rectOfInterest = rect;
    d_intervalOfInterest = QwtInterval(
        rect.left(), rect.right() ).normalized();
}

/*!
   \return "rectangle of interest"
   \sa setRectOfInterest()
*/
QRectF QwtSyntheticPointData::rectOfInterest() const
{
    return d_rectOfInterest;
}

/*!
  \brief Calculate the bounding rectangle

  This implementation iterates over all points, what could often
  be implemented much faster using the characteristics of the series.
  When there are many points it is recommended to overload and
  reimplement this method using the characteristics of the series
  ( if possible ).

  \return Bounding rectangle
*/
QRectF QwtSyntheticPointData::boundingRect() const
{
    if ( d_size == 0 ||
        !( d_interval.isValid() || d_intervalOfInterest.isValid() ) )
    {
        return QRectF( 1.0, 1.0, -2.0, -2.0 ); // something invalid
    }

    return qwtBoundingRect( *this );
}

/*!
   Calculate the point from an index

   \param index Index
   \return QPointF(x(index), y(x(index)));

   \warning For invalid indices ( index < 0 || index >= size() )
            (0, 0) is returned.
*/
QPointF QwtSyntheticPointData::sample( size_t index ) const
{
    if ( index >= d_size )
        return QPointF( 0, 0 );

    const double xValue = x( static_cast<uint>(index) );
    const double yValue = y( xValue );

    return QPointF( xValue, yValue );
}

/*!
   Calculate a x-value from an index

   x values are calculated by dividing an interval into
   equidistant steps. If !interval().isValid() the
   interval is calculated from the "rectangle of interest".

   \param index Index of the requested point
   \return Calculated x coordinate

   \sa interval(), rectOfInterest(), y()
*/
double QwtSyntheticPointData::x( uint index ) const
{
    const QwtInterval &interval = d_interval.isValid() ?
        d_interval : d_intervalOfInterest;

    if ( !interval.isValid() || d_size == 0 || index >= d_size )
        return 0.0;

    const double dx = interval.width() / d_size;
    return interval.minValue() + index * dx;
}
<commit_msg>Change tabs to spaces<commit_after>/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#include "qwt_point_data.h"
#include "qwt_math.h"
#include <string.h>

/*!
  Constructor

  \param x Array of x values
  \param y Array of y values

  \sa QwtPlotCurve::setData(), QwtPlotCurve::setSamples()
*/
QwtPointArrayData::QwtPointArrayData(
        const QVector<double> &x, const QVector<double> &y ):
    d_x( x ),
    d_y( y )
{
}

/*!
  Constructor

  \param x Array of x values
  \param y Array of y values
  \param size Size of the x and y arrays
  \sa QwtPlotCurve::setData(), QwtPlotCurve::setSamples()
*/
QwtPointArrayData::QwtPointArrayData( const double *x,
        const double *y, size_t size )
{
    d_x.resize( static_cast<int>(size) );
    ::memcpy( d_x.data(), x, size * sizeof( double ) );

    d_y.resize(static_cast<int>(size));
    ::memcpy( d_y.data(), y, size * sizeof( double ) );
}

/*!
  \brief Calculate the bounding rectangle

  The bounding rectangle is calculated once by iterating over all
  points and is stored for all following requests.

  \return Bounding rectangle
*/
QRectF QwtPointArrayData::boundingRect() const
{
    if ( d_boundingRect.width() < 0 )
        d_boundingRect = qwtBoundingRect( *this );

    return d_boundingRect;
}

//! \return Size of the data set
size_t QwtPointArrayData::size() const
{
    return qMin( d_x.size(), d_y.size() );
}

/*!
  Return the sample at position i

  \param index Index
  \return Sample at position i
*/
QPointF QwtPointArrayData::sample( size_t index ) const
{
    return QPointF( d_x[int( index )], d_y[int( index )] );
}

//! \return Array of the x-values
const QVector<double> &QwtPointArrayData::xData() const
{
    return d_x;
}

//! \return Array of the y-values
const QVector<double> &QwtPointArrayData::yData() const
{
    return d_y;
}

/*!
  Constructor

  \param x Array of x values
  \param y Array of y values
  \param size Size of the x and y arrays

  \warning The programmer must assure that the memory blocks referenced
           by the pointers remain valid during the lifetime of the
           QwtPlotCPointer object.

  \sa QwtPlotCurve::setData(), QwtPlotCurve::setRawSamples()
*/
QwtCPointerData::QwtCPointerData(
        const double *x, const double *y, size_t size ):
    d_x( x ),
    d_y( y ),
    d_size( size )
{
}

/*!
  \brief Calculate the bounding rectangle

  The bounding rectangle is calculated once by iterating over all
  points and is stored for all following requests.

  \return Bounding rectangle
*/
QRectF QwtCPointerData::boundingRect() const
{
    if ( d_boundingRect.width() < 0 )
        d_boundingRect = qwtBoundingRect( *this );

    return d_boundingRect;
}

//! \return Size of the data set
size_t QwtCPointerData::size() const
{
    return d_size;
}

/*!
  Return the sample at position i

  \param index Index
  \return Sample at position i
*/
QPointF QwtCPointerData::sample( size_t index ) const
{
    return QPointF( d_x[int( index )], d_y[int( index )] );
}

//! \return Array of the x-values
const double *QwtCPointerData::xData() const
{
    return d_x;
}

//! \return Array of the y-values
const double *QwtCPointerData::yData() const
{
    return d_y;
}

/*!
   Constructor

   \param size Number of points
   \param interval Bounding interval for the points

   \sa setInterval(), setSize()
*/
QwtSyntheticPointData::QwtSyntheticPointData(
        size_t size, const QwtInterval &interval ):
    d_size( size ),
    d_interval( interval )
{
}

/*!
  Change the number of points

  \param size Number of points
  \sa size(), setInterval()
*/
void QwtSyntheticPointData::setSize( size_t size )
{
    d_size = size;
}

/*!
  \return Number of points
  \sa setSize(), interval()
*/
size_t QwtSyntheticPointData::size() const
{
    return d_size;
}

/*!
   Set the bounding interval

   \param interval Interval
   \sa interval(), setSize()
*/
void QwtSyntheticPointData::setInterval( const QwtInterval &interval )
{
    d_interval = interval.normalized();
}

/*!
   \return Bounding interval
   \sa setInterval(), size()
*/
QwtInterval QwtSyntheticPointData::interval() const
{
    return d_interval;
}

/*!
   Set a the "rectangle of interest"

   QwtPlotSeriesItem defines the current area of the plot canvas
   as "rect of interest" ( QwtPlotSeriesItem::updateScaleDiv() ).

   If interval().isValid() == false the x values are calculated
   in the interval rect.left() -> rect.right().

   \sa rectOfInterest()
*/
void QwtSyntheticPointData::setRectOfInterest( const QRectF &rect )
{
    d_rectOfInterest = rect;
    d_intervalOfInterest = QwtInterval(
        rect.left(), rect.right() ).normalized();
}

/*!
   \return "rectangle of interest"
   \sa setRectOfInterest()
*/
QRectF QwtSyntheticPointData::rectOfInterest() const
{
    return d_rectOfInterest;
}

/*!
  \brief Calculate the bounding rectangle

  This implementation iterates over all points, what could often
  be implemented much faster using the characteristics of the series.
  When there are many points it is recommended to overload and
  reimplement this method using the characteristics of the series
  ( if possible ).

  \return Bounding rectangle
*/
QRectF QwtSyntheticPointData::boundingRect() const
{
    if ( d_size == 0 ||
        !( d_interval.isValid() || d_intervalOfInterest.isValid() ) )
    {
        return QRectF( 1.0, 1.0, -2.0, -2.0 ); // something invalid
    }

    return qwtBoundingRect( *this );
}

/*!
   Calculate the point from an index

   \param index Index
   \return QPointF(x(index), y(x(index)));

   \warning For invalid indices ( index < 0 || index >= size() )
            (0, 0) is returned.
*/
QPointF QwtSyntheticPointData::sample( size_t index ) const
{
    if ( index >= d_size )
        return QPointF( 0, 0 );

    const double xValue = x( static_cast<uint>(index) );
    const double yValue = y( xValue );

    return QPointF( xValue, yValue );
}

/*!
   Calculate a x-value from an index

   x values are calculated by dividing an interval into
   equidistant steps. If !interval().isValid() the
   interval is calculated from the "rectangle of interest".

   \param index Index of the requested point
   \return Calculated x coordinate

   \sa interval(), rectOfInterest(), y()
*/
double QwtSyntheticPointData::x( uint index ) const
{
    const QwtInterval &interval = d_interval.isValid() ?
        d_interval : d_intervalOfInterest;

    if ( !interval.isValid() || d_size == 0 || index >= d_size )
        return 0.0;

    const double dx = interval.width() / d_size;
    return interval.minValue() + index * dx;
}
<|endoftext|>


<commit_before>/**
 * @file   Path.cpp
 * @brief  Path class implementation.
 * @author zer0
 * @date   2016-10-14
 */

#include <libtbag/filesystem/Path.hpp>
#include <libtbag/filesystem/Common.hpp>
#include <libtbag/locale/Locale.hpp>
#include <libtbag/locale/Convert.hpp>

#include <algorithm>
#include <fstream>

// -------------------
NAMESPACE_LIBTBAG_OPEN
// -------------------

namespace filesystem {

Path::Path() TBAG_NOEXCEPT_EXPR(std::is_nothrow_default_constructible<std::string>::value) : _path()
{
    // EMPTY.
}

Path::Path(std::string const & path) : _path(path)
{
    // EMPTY.
}

Path::Path(char const * path) : Path(std::string(path))
{
    // EMPTY.
}

Path::Path(char const * path, update_generic const & UNUSED_PARAM(v)) : Path(std::string(path))
{
    updateGeneric();
}

Path::Path(std::string const & path, update_generic const & UNUSED_PARAM(v)) : Path(path)
{
    updateGeneric();
}

Path::Path(char const * path, update_canonical const & UNUSED_PARAM(v)) : Path(std::string(path))
{
    updateCanonical();
}

Path::Path(std::string const & path, update_canonical const & UNUSED_PARAM(v)) : Path(path)
{
    updateCanonical();
}

Path::Path(std::vector<std::string> const & nodes) : Path()
{
    append(nodes);
}

Path::Path(std::initializer_list<std::string> list) : Path()
{
    for (auto & cursor : list) {
        append(cursor);
    }
}

Path::Path(Path const & obj) : Path()
{
    copy(obj);
}

Path::Path(Path && obj) : Path()
{
    swap(obj);
}

Path::~Path()
{
    // EMPTY.
}

Path & Path::operator =(char const * path)
{
    _path.assign(path);
    return *this;
}

Path & Path::operator =(std::string const & path)
{
    if (&(_path) != &path) {
        _path = path;
    }
    return *this;
}

Path & Path::operator =(std::string && path)
{
    if (&(_path) != &path) {
        _path.swap(path);
    }
    return *this;
}

Path & Path::operator =(Path const & obj)
{
    return copy(obj);
}

Path & Path::operator =(Path && obj)
{
    swap(obj);
    return *this;
}

bool Path::operator ==(Path const & path)
{
    return getCanonicalString() == path.getCanonicalString();
}

bool Path::operator ==(std::string const & path)
{
    return getCanonicalString() == Path(path).getCanonicalString();
}

Path & Path::copy(Path const & obj)
{
    if (this != &obj) {
        _path = obj._path;
    }
    return *this;
}

void Path::swap(Path && obj)
{
    if (this != &obj) {
        _path.swap(obj._path);
    }
}

void Path::swap(Path & obj)
{
    if (this != &obj) {
        _path.swap(obj._path);
    }
}

std::string Path::getGenericString() const
{
    return getGenericWithUtf8(_path);
}

Path Path::getGeneric() const
{
    return Path(getGenericString());
}

std::string Path::getNativeString() const
{
    return getNativeWithUtf8(_path);
}

Path Path::getNative() const
{
    return Path(getNativeString());
}

Path Path::getCanonical() const
{
    return Path(splitNodesWithCanonical());
}

std::string Path::getCanonicalString() const
{
    return getCanonical().getString();
}

Path & Path::updateGeneric()
{
    setString(getGenericString());
    return *this;
}

Path & Path::updateNative()
{
    setString(getNativeString());
    return *this;
}

Path & Path::updateCanonical()
{
    setString(getCanonicalString());
    return *this;
}

std::string Path::getRootDirString() const
{
    return getRootDirWithUtf8(_path);
}

Path Path::getRootDir() const
{
    return Path(getRootDirString());
}

bool Path::isRootDir() const
{
    return Path(_path) == getRootDir();
}

bool Path::isAbsolute() const
{
    return isAbsoluteWithUtf8(_path);
}

bool Path::isRelative() const
{
    return isRelativeWithUtf8(_path);
}

std::string Path::append(std::string const & parent, std::string const & child)
{
    std::string result = parent;
    // 문지열이 공백일 경우, 경로 분리자를 삽입하면 루트가 되는 현상을 방지한다.
    if (!parent.empty() && parent.back() != PATH_SEPARATOR) {
        result += PATH_SEPARATOR;
    }
    result += child;
    return result;
}

Path & Path::append(std::string const & child)
{
    _path = append(this->_path, child);
    return *this;
}

Path & Path::append(std::vector<std::string> const & nodes)
{
    for (auto & cursor : nodes) {
        append(cursor);
    }
    return *this;
}

Path & Path::operator /=(std::string const & child)
{
    return append(child);
}

/* FRIEND */ Path operator /(Path const & path, std::string const & child)
{
    Path result = path;
    result.append(child);
    return result;
}

/* FRIEND */ Path operator /(Path && path, std::string const & child)
{
    path.append(child);
    return path;
}

Path::operator std::string() const
{
    return _path;
}

Path::operator char const * () const
{
    return _path.c_str();
}

std::string Path::getParentString() const
{
    if (isAbsolute()) {
        return removeLastNodeWithUtf8(_path);
    }
    return appendParentWithUtf8(_path);
}

Path Path::getParent() const
{
    return Path(getParentString());
}

std::vector<std::string> Path::splitNodes() const
{
    return splitNodesWithUtf8(_path);
}

std::vector<std::string> Path::splitNodesWithCanonical() const
{
    std::vector<std::string> result;
    std::vector<std::string> nodes = splitNodes();
    using NodeItr = std::vector<std::string>::iterator;

    NodeItr itr;
    NodeItr end = nodes.end();

    if (isAbsolute() == true) {
        itr = nodes.begin();
    } else {
        if (nodes.size() >= 1 && nodes.at(0) == HOME_DIRECTORY_SHORTCUT) {
            result = Path(getHomeDir()).splitNodes();
            itr = nodes.begin() + 1;
        } else {
            result = Path(getWorkDir()).splitNodes();
            itr = nodes.begin();
        }
    }

    for (; itr != end; ++itr) {
        if (*itr == CURRENT_DIRECTORY_SHORTCUT) {
            // skip.
        } else if (*itr == PARENT_DIRECTORY_SHORTCUT) {
            result.pop_back();
        } else {
            result.push_back(*itr);
        }
    }

    return result;
}

std::string Path::getName() const
{
    auto nodes = splitNodes();
    if (nodes.rbegin() == nodes.rend()) {
        return std::string();
    }
    return *nodes.rbegin();
}

template <typename Predicated>
inline auto fromUtf8(std::string const & path, Predicated predicated) -> decltype(predicated(path))
{
    std::locale const NATIVE_LOCALE = std::locale(locale::getGlobalLocaleName());
    if (locale::isUtf8Encoding(NATIVE_LOCALE) == false) {
        std::string native_path;
        if (locale::convertFromUtf8(path, locale::getEncoding(NATIVE_LOCALE), native_path)) {
            return predicated(native_path);
        }
    }
    return predicated(path);
}

bool Path::exists() const
{
    return fromUtf8(_path, libtbag::filesystem::exists);
}

bool Path::isExecutable() const
{
    return fromUtf8(_path, libtbag::filesystem::isExecutable);
}

bool Path::isWritable() const
{
    return fromUtf8(_path, libtbag::filesystem::isWritable);
}

bool Path::isReadable() const
{
    return fromUtf8(_path, libtbag::filesystem::isReadable);
}

bool Path::isRegularFile() const
{
    return fromUtf8(_path, libtbag::filesystem::isRegularFile);
}

bool Path::isDirectory() const
{
    return fromUtf8(_path, libtbag::filesystem::isDirectory);
}

bool Path::createDir() const
{
    auto parent = getParent();
    if (parent.isDirectory() && parent.isWritable() && exists() == false) {
        return fromUtf8(_path, libtbag::filesystem::createDirectory);
    }
    return false;
}

bool Path::createDirWithRecursive() const
{
    // @formatter:off
    if (createDir()) { return  true; }
    if (isRootDir()) { return false; }
    // @formatter:on

    if (getParent().createDirWithRecursive()) {
        return createDir();
    }
    return false;
}

bool Path::remove() const
{
    if (isDirectory()) {
        return removeDir();
    } else if (isRegularFile()) {
        return removeFile();
    }
    return false;
}

bool Path::removeFile() const
{
    if (isRegularFile() && isWritable()) {
        return fromUtf8(_path, libtbag::filesystem::removeFile);
    }
    return false;
}

bool Path::removeDir() const
{
    if (isDirectory() && isWritable()) {
        return fromUtf8(_path, libtbag::filesystem::removeDirectory);
    }
    return false;
}

bool Path::removeDirWithRecursive() const
{
    return fromUtf8(_path, libtbag::filesystem::removeAll);
}

std::vector<Path> Path::scanDir() const
{
    std::vector<Path> result;
    for (auto & path : fromUtf8(_path, libtbag::filesystem::scanDir)) {
        result.push_back(Path(_path) / path);
    }
    return result;
}

std::size_t Path::size() const
{
    std::ifstream f(getCanonicalString(), std::ios_base::ate | std::ios_base::binary);
    if (f.eof() == false && f.fail() == false) {
        return static_cast<std::size_t>(f.tellg()/*std::streamoff*/);
    }
    return 0U;
}

template <typename Predicated>
inline auto toUtf8(Predicated predicated) -> decltype(predicated())
{
    std::locale const NATIVE_LOCALE = std::locale(locale::getGlobalLocaleName());
    std::string native_path = predicated();

    if (locale::isUtf8Encoding(NATIVE_LOCALE) == false) {
        std::string utf8_path;
        if (locale::convertToUtf8(native_path, locale::getEncoding(NATIVE_LOCALE), utf8_path)) {
            return utf8_path;
        }
    }
    return native_path;
}

Path Path::getWorkDir()
{
    return Path(toUtf8(libtbag::filesystem::getWorkDir));
}

Path Path::getHomeDir()
{
    return Path(toUtf8(libtbag::filesystem::getHomeDir));
}

Path Path::getExePath()
{
    return Path(toUtf8(libtbag::filesystem::getExePath));
}

Path Path::getExeDir()
{
    return Path(removeLastNodeWithUtf8(toUtf8(libtbag::filesystem::getExePath)));
}

} // namespace filesystem

// --------------------
NAMESPACE_LIBTBAG_CLOSE
// --------------------

<commit_msg>Fix the some error in MSVC 14.<commit_after>/**
 * @file   Path.cpp
 * @brief  Path class implementation.
 * @author zer0
 * @date   2016-10-14
 */

#include <libtbag/filesystem/Path.hpp>
#include <libtbag/filesystem/Common.hpp>
#include <libtbag/locale/Locale.hpp>
#include <libtbag/locale/Convert.hpp>

#include <algorithm>
#include <fstream>

// -------------------
NAMESPACE_LIBTBAG_OPEN
// -------------------

namespace filesystem {

Path::Path() TBAG_NOEXCEPT_EXPR(std::is_nothrow_default_constructible<std::string>::value) : _path()
{
    // EMPTY.
}

Path::Path(std::string const & path) : _path(path)
{
    // EMPTY.
}

Path::Path(char const * path) : Path(std::string(path))
{
    // EMPTY.
}

Path::Path(char const * path, update_generic const & UNUSED_PARAM(v)) : Path(std::string(path))
{
    updateGeneric();
}

Path::Path(std::string const & path, update_generic const & UNUSED_PARAM(v)) : Path(path)
{
    updateGeneric();
}

Path::Path(char const * path, update_canonical const & UNUSED_PARAM(v)) : Path(std::string(path))
{
    updateCanonical();
}

Path::Path(std::string const & path, update_canonical const & UNUSED_PARAM(v)) : Path(path)
{
    updateCanonical();
}

Path::Path(std::vector<std::string> const & nodes) : Path()
{
    append(nodes);
}

Path::Path(std::initializer_list<std::string> list) : Path()
{
    for (auto & cursor : list) {
        append(cursor);
    }
}

Path::Path(Path const & obj) : Path()
{
    copy(obj);
}

Path::Path(Path && obj) : Path()
{
    swap(obj);
}

Path::~Path()
{
    // EMPTY.
}

Path & Path::operator =(char const * path)
{
    _path.assign(path);
    return *this;
}

Path & Path::operator =(std::string const & path)
{
    if (&(_path) != &path) {
        _path = path;
    }
    return *this;
}

Path & Path::operator =(std::string && path)
{
    if (&(_path) != &path) {
        _path.swap(path);
    }
    return *this;
}

Path & Path::operator =(Path const & obj)
{
    return copy(obj);
}

Path & Path::operator =(Path && obj)
{
    swap(obj);
    return *this;
}

bool Path::operator ==(Path const & path)
{
    return getCanonicalString() == path.getCanonicalString();
}

bool Path::operator ==(std::string const & path)
{
    return getCanonicalString() == Path(path).getCanonicalString();
}

Path & Path::copy(Path const & obj)
{
    if (this != &obj) {
        _path = obj._path;
    }
    return *this;
}

void Path::swap(Path && obj)
{
    if (this != &obj) {
        _path.swap(obj._path);
    }
}

void Path::swap(Path & obj)
{
    if (this != &obj) {
        _path.swap(obj._path);
    }
}

std::string Path::getGenericString() const
{
    return getGenericWithUtf8(_path);
}

Path Path::getGeneric() const
{
    return Path(getGenericString());
}

std::string Path::getNativeString() const
{
    return getNativeWithUtf8(_path);
}

Path Path::getNative() const
{
    return Path(getNativeString());
}

Path Path::getCanonical() const
{
    return Path(splitNodesWithCanonical());
}

std::string Path::getCanonicalString() const
{
    return getCanonical().getString();
}

Path & Path::updateGeneric()
{
    setString(getGenericString());
    return *this;
}

Path & Path::updateNative()
{
    setString(getNativeString());
    return *this;
}

Path & Path::updateCanonical()
{
    setString(getCanonicalString());
    return *this;
}

std::string Path::getRootDirString() const
{
    return getRootDirWithUtf8(_path);
}

Path Path::getRootDir() const
{
    return Path(getRootDirString());
}

bool Path::isRootDir() const
{
    return Path(_path) == getRootDir();
}

bool Path::isAbsolute() const
{
    return isAbsoluteWithUtf8(_path);
}

bool Path::isRelative() const
{
    return isRelativeWithUtf8(_path);
}

std::string Path::append(std::string const & parent, std::string const & child)
{
    std::string result = parent;
    // 문지열이 공백일 경우, 경로 분리자를 삽입하면 루트가 되는 현상을 방지한다.
    if (!parent.empty() && parent.back() != PATH_SEPARATOR) {
        result += PATH_SEPARATOR;
    }
    result += child;
    return result;
}

Path & Path::append(std::string const & child)
{
    _path = append(this->_path, child);
    return *this;
}

Path & Path::append(std::vector<std::string> const & nodes)
{
    for (auto & cursor : nodes) {
        append(cursor);
    }
    return *this;
}

Path & Path::operator /=(std::string const & child)
{
    return append(child);
}

/* FRIEND */ Path operator /(Path const & path, std::string const & child)
{
    Path result = path;
    result.append(child);
    return result;
}

/* FRIEND */ Path operator /(Path && path, std::string const & child)
{
    path.append(child);
    return path;
}

Path::operator std::string() const
{
    return _path;
}

Path::operator char const * () const
{
    return _path.c_str();
}

std::string Path::getParentString() const
{
    if (isAbsolute()) {
        return removeLastNodeWithUtf8(_path);
    }
    return appendParentWithUtf8(_path);
}

Path Path::getParent() const
{
    return Path(getParentString());
}

std::vector<std::string> Path::splitNodes() const
{
    return splitNodesWithUtf8(_path);
}

std::vector<std::string> Path::splitNodesWithCanonical() const
{
    std::vector<std::string> result;
    std::vector<std::string> nodes = splitNodes();
    using NodeItr = std::vector<std::string>::iterator;

    NodeItr itr;
    NodeItr end = nodes.end();

    if (isAbsolute() == true) {
        itr = nodes.begin();
    } else {
        if (nodes.size() >= 1 && nodes.at(0) == HOME_DIRECTORY_SHORTCUT) {
            result = Path(getHomeDir()).splitNodes();
            itr = nodes.begin() + 1;
        } else {
            result = Path(getWorkDir()).splitNodes();
            itr = nodes.begin();
        }
    }

    for (; itr != end; ++itr) {
        if (*itr == CURRENT_DIRECTORY_SHORTCUT) {
            // skip.
        } else if (*itr == PARENT_DIRECTORY_SHORTCUT) {
            result.pop_back();
        } else {
            result.push_back(*itr);
        }
    }

    return result;
}

std::string Path::getName() const
{
    auto nodes = splitNodes();
    if (nodes.rbegin() == nodes.rend()) {
        return std::string();
    }
    return *nodes.rbegin();
}

template <typename Predicated>
inline bool isFromUtf8(std::string const & path, Predicated predicated)
{
    std::locale const NATIVE_LOCALE = std::locale(locale::getGlobalLocaleName());
    if (locale::isUtf8Encoding(NATIVE_LOCALE) == false) {
        std::string native_path;
        if (locale::convertFromUtf8(path, locale::getEncoding(NATIVE_LOCALE), native_path)) {
            return predicated(native_path);
        }
    }
    return predicated(path);
}

bool Path::exists() const
{
    return isFromUtf8(_path, libtbag::filesystem::exists);
}

bool Path::isExecutable() const
{
    return isFromUtf8(_path, libtbag::filesystem::isExecutable);
}

bool Path::isWritable() const
{
    return isFromUtf8(_path, libtbag::filesystem::isWritable);
}

bool Path::isReadable() const
{
    return isFromUtf8(_path, libtbag::filesystem::isReadable);
}

bool Path::isRegularFile() const
{
    return isFromUtf8(_path, libtbag::filesystem::isRegularFile);
}

bool Path::isDirectory() const
{
    return isFromUtf8(_path, libtbag::filesystem::isDirectory);
}

bool Path::createDir() const
{
    auto parent = getParent();
    if (parent.isDirectory() && parent.isWritable() && exists() == false) {
        return isFromUtf8(_path, libtbag::filesystem::createDirectory);
    }
    return false;
}

bool Path::createDirWithRecursive() const
{
    // @formatter:off
    if (createDir()) { return  true; }
    if (isRootDir()) { return false; }
    // @formatter:on

    if (getParent().createDirWithRecursive()) {
        return createDir();
    }
    return false;
}

bool Path::remove() const
{
    if (isDirectory()) {
        return removeDir();
    } else if (isRegularFile()) {
        return removeFile();
    }
    return false;
}

bool Path::removeFile() const
{
    if (isRegularFile() && isWritable()) {
        return isFromUtf8(_path, libtbag::filesystem::removeFile);
    }
    return false;
}

bool Path::removeDir() const
{
    if (isDirectory() && isWritable()) {
        return isFromUtf8(_path, libtbag::filesystem::removeDirectory);
    }
    return false;
}

bool Path::removeDirWithRecursive() const
{
    return isFromUtf8(_path, libtbag::filesystem::removeAll);
}

std::vector<Path> Path::scanDir() const
{
    std::vector<Path> result;
    for (auto & path : libtbag::filesystem::scanDir(_path)) {
        result.push_back(Path(_path) / path);
    }
    return result;
}

std::size_t Path::size() const
{
    std::ifstream f(getCanonicalString(), std::ios_base::ate | std::ios_base::binary);
    if (f.eof() == false && f.fail() == false) {
        return static_cast<std::size_t>(f.tellg()/*std::streamoff*/);
    }
    return 0U;
}

template <typename Predicated>
inline std::string toUtf8(Predicated predicated)
{
    std::locale const NATIVE_LOCALE = std::locale(locale::getGlobalLocaleName());
    std::string native_path = predicated();

    if (locale::isUtf8Encoding(NATIVE_LOCALE) == false) {
        std::string utf8_path;
        if (locale::convertToUtf8(native_path, locale::getEncoding(NATIVE_LOCALE), utf8_path)) {
            return utf8_path;
        }
    }
    return native_path;
}

Path Path::getWorkDir()
{
    return Path(toUtf8(libtbag::filesystem::getWorkDir));
}

Path Path::getHomeDir()
{
    return Path(toUtf8(libtbag::filesystem::getHomeDir));
}

Path Path::getExePath()
{
    return Path(toUtf8(libtbag::filesystem::getExePath));
}

Path Path::getExeDir()
{
    return Path(removeLastNodeWithUtf8(toUtf8(libtbag::filesystem::getExePath)));
}

} // namespace filesystem

// --------------------
NAMESPACE_LIBTBAG_CLOSE
// --------------------

<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH
#define DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH

#include <dune/common/dynvector.hh>
#include <dune/common/version.hh>
#include <dune/common/typetraits.hh>

#if DUNE_VERSION_NEWER(DUNE_COMMON, 3, 9) // EXADUNE
#include <dune/geometry/referenceelements.hh>
#else
#include <dune/geometry/genericreferenceelements.hh>
#endif

#include <dune/stuff/common/exceptions.hh>
#include <dune/stuff/common/type_utils.hh>

#include "../interface.hh"

namespace Dune {
namespace GDT {
namespace Spaces {

template <class ImpTraits, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols = 1>
class CGInterface : public SpaceInterface<ImpTraits, domainDim, rangeDim, rangeDimCols>
{
  typedef SpaceInterface<ImpTraits, domainDim, rangeDim, rangeDimCols> BaseType;
  typedef CGInterface<ImpTraits, domainDim, RangeFieldImp, rangeDim, rangeDimCols> ThisType;

  static constexpr RangeFieldImp compare_tolerance_ = 1e-13;

public:
  typedef ImpTraits Traits;

  using BaseType::polOrder;

  using typename BaseType::DomainFieldType;
  using BaseType::dimDomain;
  using typename BaseType::DomainType;

  typedef typename Traits::RangeFieldType RangeFieldType;
  using BaseType::dimRange;
  using BaseType::dimRangeCols;

  using typename BaseType::EntityType;
  using typename BaseType::IntersectionType;
  using typename BaseType::BoundaryInfoType;
  using typename BaseType::PatternType;

  /**
   * \defgroup interface ´´These methods have to be implemented!''
   * @{
   **/
  std::vector<DomainType> lagrange_points(const EntityType& entity) const
  {
    CHECK_CRTP(this->as_imp().lagrange_points(entity));
    return this->as_imp().lagrange_points(entity);
  } // ... lagrange_points(...)

  std::set<size_t> local_dirichlet_DoFs(const EntityType& entity, const BoundaryInfoType& boundaryInfo) const
  {
    CHECK_CRTP(this->as_imp().local_dirichlet_DoFs(entity, boundaryInfo));
    return this->as_imp().local_dirichlet_DoFs(entity, boundaryInfo);
  } // ... local_dirichlet_DoFs(...)
  /** @} */

  /**
   * \defgroup provided ´´These methods are provided by the interface for convenience.''
   * @{
   **/
  std::vector<DomainType> lagrange_points_order_1(const EntityType& entity) const
  {
    // check
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    assert(this->grid_view().indexSet().contains(entity));
    // get the basis and reference element
    const auto basis = this->base_function_set(entity);
    typedef typename BaseType::BaseFunctionSetType::RangeType RangeType;
    std::vector<RangeType> tmp_basis_values(basis.size(), RangeType(0));
    const auto& reference_element = ReferenceElements<DomainFieldType, dimDomain>::general(entity.type());
    const int num_vertices = reference_element.size(dimDomain);
    assert(num_vertices >= 0);
    assert(size_t(num_vertices) == basis.size() && "This should not happen with polOrder 1!");
    // prepare return vector
    std::vector<DomainType> local_vertices(num_vertices, DomainType(0));
    // loop over all vertices
    for (int ii = 0; ii < num_vertices; ++ii) {
      // get the local coordinate of the iith vertex
      const auto local_vertex = reference_element.position(ii, dimDomain);
      // evaluate the basefunctionset
      basis.evaluate(local_vertex, tmp_basis_values);
      // find the basis function that evaluates to one here (has to be only one!)
      size_t ones     = 0;
      size_t zeros    = 0;
      size_t failures = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj) {
        if (std::abs((tmp_basis_values)[jj][0] - RangeFieldType(1)) < compare_tolerance_) {
          local_vertices[jj] = local_vertex;
          ++ones;
        } else if (std::abs((tmp_basis_values)[jj][0]) < compare_tolerance_)
          ++zeros;
        else
          ++failures;
      }
      assert(ones == 1 && zeros == (basis.size() - 1) && failures == 0 && "This must not happen for polOrder 1!");
    }
    return local_vertices;
  } // ... lagrange_points_order_1(...)

  std::set<size_t> local_dirichlet_DoFs_order_1(const EntityType& entity, const BoundaryInfoType& boundaryInfo) const
  {
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    // check
    assert(this->grid_view().indexSet().contains(entity));
    // prepare
    std::set<size_t> localDirichletDofs;
    std::vector<DomainType> dirichlet_vertices;
    // get all dirichlet vertices of this entity, therefore
    // * loop over all intersections
    const auto intersection_it_end = this->grid_view().iend(entity);
    for (auto intersection_it = this->grid_view().ibegin(entity); intersection_it != intersection_it_end;
         ++intersection_it) {
      // only work on dirichlet ones
      const auto& intersection = *intersection_it;
      // actual dirichlet intersections + process boundaries for parallel runs
      if (boundaryInfo.dirichlet(intersection) || (!intersection.neighbor() && !intersection.boundary())) {
        // and get the vertices of the intersection
        const auto geometry = intersection.geometry();
        for (int cc = 0; cc < geometry.corners(); ++cc)
          dirichlet_vertices.emplace_back(entity.geometry().local(geometry.corner(cc)));
      } // only work on dirichlet ones
    } // loop over all intersections
    // find the corresponding basis functions
    const auto basis = this->base_function_set(entity);
    typedef typename BaseType::BaseFunctionSetType::RangeType RangeType;
    std::vector<RangeType> tmp_basis_values(basis.size(), RangeType(0));
    for (size_t cc = 0; cc < dirichlet_vertices.size(); ++cc) {
      // find the basis function that evaluates to one here (has to be only one!)
      basis.evaluate(dirichlet_vertices[cc], tmp_basis_values);
      size_t ones     = 0;
      size_t zeros    = 0;
      size_t failures = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj) {
        if (std::abs(tmp_basis_values[jj][0] - RangeFieldType(1)) < compare_tolerance_) {
          localDirichletDofs.insert(jj);
          ++ones;
        } else if (std::abs(tmp_basis_values[jj][0]) < compare_tolerance_)
          ++zeros;
        else
          ++failures;
      }
      assert(ones == 1 && zeros == (basis.size() - 1) && failures == 0 && "This must not happen for polOrder 1!");
    }
    return localDirichletDofs;
  } // ... local_dirichlet_DoFs_order_1(...)

  using BaseType::compute_pattern;

  template <class G, class S, int d, int r, int rC>
  PatternType compute_pattern(const GridView<G>& local_grid_view, const SpaceInterface<S, d, r, rC>& ansatz_space) const
  {
    return BaseType::compute_volume_pattern(local_grid_view, ansatz_space);
  } // ... compute_pattern(...)

  using BaseType::local_constraints;

  template <class S, int d, int r, int rC, class ConstraintsType>
  void local_constraints(const SpaceInterface<S, d, r, rC>& /*other*/, const EntityType& /*entity*/,
                         ConstraintsType& /*ret*/) const
  {
    static_assert(AlwaysFalse<S>::value, "Not implemented for these constraints!");
  } // ... local_constraints(...)

  template <class S, int d, int r, int rC>
  void local_constraints(const SpaceInterface<S, d, r, rC>& other, const EntityType& entity,
                         Constraints::Dirichlet<IntersectionType, RangeFieldType>& ret) const
  {
    // check
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    assert(this->grid_view().indexSet().contains(entity));
    const std::set<size_t> localDirichletDofs = this->local_dirichlet_DoFs(entity, ret.boundary_info());
    const size_t numRows                      = localDirichletDofs.size();
    Dune::DynamicVector<size_t> tmpMappedRows;
    Dune::DynamicVector<size_t> tmpMappedCols;
    if (numRows > 0) {
      const size_t numCols = this->mapper().numDofs(entity);
      ret.set_size(numRows, numCols);
      this->mapper().globalIndices(entity, tmpMappedRows);
      other.mapper().globalIndices(entity, tmpMappedCols);
      size_t localRow = 0;
      for (const size_t& localDirichletDofIndex : localDirichletDofs) {
        ret.global_row(localRow) = tmpMappedRows[localDirichletDofIndex];
        for (size_t jj = 0; jj < ret.cols(); ++jj) {
          ret.global_col(jj) = tmpMappedCols[jj];
          if (tmpMappedCols[jj] == tmpMappedRows[localDirichletDofIndex])
            ret.value(localRow, jj) = ret.set_row() ? 1 : 0;
          else
            ret.value(localRow, jj) = 0;
        }
        ++localRow;
      }
    } else {
      ret.set_size(0, 0);
    }
  } // ... local_constraints(..., Constraints::Dirichlet< ... > ...)
  /** @} */
}; // class CGInterface

} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH
<commit_msg>[spaces.cg.interface] fix headerguard<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_CG_INTERFACE_HH
#define DUNE_GDT_SPACES_CG_INTERFACE_HH

#include <dune/common/dynvector.hh>
#include <dune/common/version.hh>
#include <dune/common/typetraits.hh>

#if DUNE_VERSION_NEWER(DUNE_COMMON, 3, 9) // EXADUNE
#include <dune/geometry/referenceelements.hh>
#else
#include <dune/geometry/genericreferenceelements.hh>
#endif

#include <dune/stuff/common/exceptions.hh>
#include <dune/stuff/common/type_utils.hh>

#include "../interface.hh"

namespace Dune {
namespace GDT {
namespace Spaces {

template <class ImpTraits, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols = 1>
class CGInterface : public SpaceInterface<ImpTraits, domainDim, rangeDim, rangeDimCols>
{
  typedef SpaceInterface<ImpTraits, domainDim, rangeDim, rangeDimCols> BaseType;
  typedef CGInterface<ImpTraits, domainDim, RangeFieldImp, rangeDim, rangeDimCols> ThisType;

  static constexpr RangeFieldImp compare_tolerance_ = 1e-13;

public:
  typedef ImpTraits Traits;

  using BaseType::polOrder;

  using typename BaseType::DomainFieldType;
  using BaseType::dimDomain;
  using typename BaseType::DomainType;

  typedef typename Traits::RangeFieldType RangeFieldType;
  using BaseType::dimRange;
  using BaseType::dimRangeCols;

  using typename BaseType::EntityType;
  using typename BaseType::IntersectionType;
  using typename BaseType::BoundaryInfoType;
  using typename BaseType::PatternType;

  /**
   * \defgroup interface ´´These methods have to be implemented!''
   * @{
   **/
  std::vector<DomainType> lagrange_points(const EntityType& entity) const
  {
    CHECK_CRTP(this->as_imp().lagrange_points(entity));
    return this->as_imp().lagrange_points(entity);
  } // ... lagrange_points(...)

  std::set<size_t> local_dirichlet_DoFs(const EntityType& entity, const BoundaryInfoType& boundaryInfo) const
  {
    CHECK_CRTP(this->as_imp().local_dirichlet_DoFs(entity, boundaryInfo));
    return this->as_imp().local_dirichlet_DoFs(entity, boundaryInfo);
  } // ... local_dirichlet_DoFs(...)
  /** @} */

  /**
   * \defgroup provided ´´These methods are provided by the interface for convenience.''
   * @{
   **/
  std::vector<DomainType> lagrange_points_order_1(const EntityType& entity) const
  {
    // check
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    assert(this->grid_view().indexSet().contains(entity));
    // get the basis and reference element
    const auto basis = this->base_function_set(entity);
    typedef typename BaseType::BaseFunctionSetType::RangeType RangeType;
    std::vector<RangeType> tmp_basis_values(basis.size(), RangeType(0));
    const auto& reference_element = ReferenceElements<DomainFieldType, dimDomain>::general(entity.type());
    const int num_vertices = reference_element.size(dimDomain);
    assert(num_vertices >= 0);
    assert(size_t(num_vertices) == basis.size() && "This should not happen with polOrder 1!");
    // prepare return vector
    std::vector<DomainType> local_vertices(num_vertices, DomainType(0));
    // loop over all vertices
    for (int ii = 0; ii < num_vertices; ++ii) {
      // get the local coordinate of the iith vertex
      const auto local_vertex = reference_element.position(ii, dimDomain);
      // evaluate the basefunctionset
      basis.evaluate(local_vertex, tmp_basis_values);
      // find the basis function that evaluates to one here (has to be only one!)
      size_t ones     = 0;
      size_t zeros    = 0;
      size_t failures = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj) {
        if (std::abs((tmp_basis_values)[jj][0] - RangeFieldType(1)) < compare_tolerance_) {
          local_vertices[jj] = local_vertex;
          ++ones;
        } else if (std::abs((tmp_basis_values)[jj][0]) < compare_tolerance_)
          ++zeros;
        else
          ++failures;
      }
      assert(ones == 1 && zeros == (basis.size() - 1) && failures == 0 && "This must not happen for polOrder 1!");
    }
    return local_vertices;
  } // ... lagrange_points_order_1(...)

  std::set<size_t> local_dirichlet_DoFs_order_1(const EntityType& entity, const BoundaryInfoType& boundaryInfo) const
  {
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    // check
    assert(this->grid_view().indexSet().contains(entity));
    // prepare
    std::set<size_t> localDirichletDofs;
    std::vector<DomainType> dirichlet_vertices;
    // get all dirichlet vertices of this entity, therefore
    // * loop over all intersections
    const auto intersection_it_end = this->grid_view().iend(entity);
    for (auto intersection_it = this->grid_view().ibegin(entity); intersection_it != intersection_it_end;
         ++intersection_it) {
      // only work on dirichlet ones
      const auto& intersection = *intersection_it;
      // actual dirichlet intersections + process boundaries for parallel runs
      if (boundaryInfo.dirichlet(intersection) || (!intersection.neighbor() && !intersection.boundary())) {
        // and get the vertices of the intersection
        const auto geometry = intersection.geometry();
        for (int cc = 0; cc < geometry.corners(); ++cc)
          dirichlet_vertices.emplace_back(entity.geometry().local(geometry.corner(cc)));
      } // only work on dirichlet ones
    } // loop over all intersections
    // find the corresponding basis functions
    const auto basis = this->base_function_set(entity);
    typedef typename BaseType::BaseFunctionSetType::RangeType RangeType;
    std::vector<RangeType> tmp_basis_values(basis.size(), RangeType(0));
    for (size_t cc = 0; cc < dirichlet_vertices.size(); ++cc) {
      // find the basis function that evaluates to one here (has to be only one!)
      basis.evaluate(dirichlet_vertices[cc], tmp_basis_values);
      size_t ones     = 0;
      size_t zeros    = 0;
      size_t failures = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj) {
        if (std::abs(tmp_basis_values[jj][0] - RangeFieldType(1)) < compare_tolerance_) {
          localDirichletDofs.insert(jj);
          ++ones;
        } else if (std::abs(tmp_basis_values[jj][0]) < compare_tolerance_)
          ++zeros;
        else
          ++failures;
      }
      assert(ones == 1 && zeros == (basis.size() - 1) && failures == 0 && "This must not happen for polOrder 1!");
    }
    return localDirichletDofs;
  } // ... local_dirichlet_DoFs_order_1(...)

  using BaseType::compute_pattern;

  template <class G, class S, int d, int r, int rC>
  PatternType compute_pattern(const GridView<G>& local_grid_view, const SpaceInterface<S, d, r, rC>& ansatz_space) const
  {
    return BaseType::compute_volume_pattern(local_grid_view, ansatz_space);
  } // ... compute_pattern(...)

  using BaseType::local_constraints;

  template <class S, int d, int r, int rC, class ConstraintsType>
  void local_constraints(const SpaceInterface<S, d, r, rC>& /*other*/, const EntityType& /*entity*/,
                         ConstraintsType& /*ret*/) const
  {
    static_assert(AlwaysFalse<S>::value, "Not implemented for these constraints!");
  } // ... local_constraints(...)

  template <class S, int d, int r, int rC>
  void local_constraints(const SpaceInterface<S, d, r, rC>& other, const EntityType& entity,
                         Constraints::Dirichlet<IntersectionType, RangeFieldType>& ret) const
  {
    // check
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    assert(this->grid_view().indexSet().contains(entity));
    const std::set<size_t> localDirichletDofs = this->local_dirichlet_DoFs(entity, ret.boundary_info());
    const size_t numRows                      = localDirichletDofs.size();
    Dune::DynamicVector<size_t> tmpMappedRows;
    Dune::DynamicVector<size_t> tmpMappedCols;
    if (numRows > 0) {
      const size_t numCols = this->mapper().numDofs(entity);
      ret.set_size(numRows, numCols);
      this->mapper().globalIndices(entity, tmpMappedRows);
      other.mapper().globalIndices(entity, tmpMappedCols);
      size_t localRow = 0;
      for (const size_t& localDirichletDofIndex : localDirichletDofs) {
        ret.global_row(localRow) = tmpMappedRows[localDirichletDofIndex];
        for (size_t jj = 0; jj < ret.cols(); ++jj) {
          ret.global_col(jj) = tmpMappedCols[jj];
          if (tmpMappedCols[jj] == tmpMappedRows[localDirichletDofIndex])
            ret.value(localRow, jj) = ret.set_row() ? 1 : 0;
          else
            ret.value(localRow, jj) = 0;
        }
        ++localRow;
      }
    } else {
      ret.set_size(0, 0);
    }
  } // ... local_constraints(..., Constraints::Dirichlet< ... > ...)
  /** @} */
}; // class CGInterface

} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_CG_INTERFACE_HH
<|endoftext|>


<commit_before>// This file is part of the dune-stuff project:
//   http://users.dune-project.org/projects/dune-stuff/
// Copyright Holders: Felix Albrecht, Rene Milk
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_GRID_BOUNDARYINFO_HH
#define DUNE_STUFF_GRID_BOUNDARYINFO_HH

#include <map>
#include <set>
#include <string>
#include <vector>
#include <memory>

#include <dune/common/exceptions.hh>
#include <dune/common/fvector.hh>

#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/color.hh>
#include <dune/stuff/common/vector.hh>
#include <dune/stuff/common/float_cmp.hh>

namespace Dune {
namespace Stuff {

template< class IntersectionImp >
class GridboundaryInterface
{
public:
  typedef IntersectionImp IntersectionType;

  static const std::string id()
  {
    return "boundaryinfo";
  }

  virtual ~GridboundaryInterface() {}

  virtual bool dirichlet(const IntersectionType&) const = 0;

  virtual bool neumann(const IntersectionType&) const = 0;
}; // class GridboundaryInterface

template< class IntersectionImp >
class GridboundaryAllDirichlet
  : public GridboundaryInterface< IntersectionImp >
{
  typedef GridboundaryInterface< IntersectionImp >  BaseType;
public:
  typedef typename BaseType::IntersectionType       IntersectionType;

  static const std::string id()
  {
    return BaseType::id() + ".alldirichlet";
  }

  static Dune::ParameterTree defaultSettings(const std::string /*subName*/ = "")
  {
    return Dune::ParameterTree();
  }

  GridboundaryAllDirichlet() {}

  virtual bool dirichlet(const IntersectionType& intersection) const
  {
    if (intersection.boundary())
      return true;
    else
      return false;
  } // virtual bool dirichlet(const IntersectionType& intersection) const

  virtual bool neumann(const IntersectionType&) const
  {
    return false;
  }
}; // class GridboundaryAllDirichlet

template< class IntersectionImp >
class GridboundaryAllNeumann
  : public GridboundaryInterface< IntersectionImp >
{
  typedef GridboundaryInterface< IntersectionImp >  BaseType;
public:
  typedef typename BaseType::IntersectionType       IntersectionType;

  static const std::string id()
  {
    return BaseType::id() + ".allneumann";
  }

  static Dune::ParameterTree defaultSettings(const std::string /*subName*/ = "")
  {
    return Dune::ParameterTree();
  }

  GridboundaryAllNeumann() {}

  virtual bool dirichlet(const IntersectionType& /*intersection*/) const
  {
    return false;
  }

  virtual bool neumann(const IntersectionType& intersection) const
  {
    return intersection.boundary();
  } // virtual bool neumann(const IntersectionType& intersection) const
}; // class GridboundaryAllNeumann

template< class IntersectionImp >
class GridboundaryIdBased
  : public GridboundaryInterface< IntersectionImp >
{
  typedef GridboundaryInterface< IntersectionImp >  BaseType;
public:
  typedef GridboundaryIdBased< IntersectionImp >    ThisType;
  typedef typename BaseType::IntersectionType       IntersectionType;

  static const std::string id()
  {
    return BaseType::id() + ".idbased";
  }

  typedef int                                 IdType;
  typedef std::set< IdType >                  IdSetType;
  typedef std::map< std::string, IdSetType >  IdSetMapType;

  GridboundaryIdBased(const IdSetMapType boundaryInfoMap)
      : boundaryInfoMap_(boundaryInfoMap)
      , hasDirichlet_(boundaryInfoMap_.find("dirichlet") != boundaryInfoMap_.end())
      , hasNeumann_(boundaryInfoMap_.find("neumann") != boundaryInfoMap_.end())
  {}

  GridboundaryIdBased(const Dune::ParameterTree& settings, const std::string subName = id())
  {
    const Common::ExtendedParameterTree ext_settings = settings.hasSub(subName) ? settings.sub(subName) : settings;
    const std::vector< int > dirichletIds = ext_settings.getVector< int >("dirichlet", 0, 0);
    const std::vector< int > neumannIds = ext_settings.getVector< int >("neumann", 0, 0);
    boundaryInfoMap_.insert(std::pair< std::string, IdSetType >("dirichlet", IdSetType(dirichletIds.begin(), dirichletIds.end())));
    boundaryInfoMap_.emplace("neumann", IdSetType(neumannIds.begin(), neumannIds.end()));
    hasDirichlet_ = boundaryInfoMap_.find("dirichlet") != boundaryInfoMap_.end();
    hasNeumann_ = boundaryInfoMap_.find("neumann") != boundaryInfoMap_.end();
  }

  static Dune::ParameterTree defaultSettings(const std::string subName = "")
  {
    Dune::ParameterTree description;
    description["dirichlet"] = "[1; 2; 3]";
    description["neumann"] = "[4]";
    if (subName.empty())
      return description;
    else {
      Dune::Stuff::Common::ExtendedParameterTree extendedDescription;
      extendedDescription.add(description, subName);
      return extendedDescription;
    }
  }

  static ThisType* create(const Dune::ParameterTree& settings, const std::string subName = id()) {
    return new ThisType(settings, subName);
  }

  const IdSetMapType& boundaryInfoMap() const
  {
    return boundaryInfoMap_;
  }

  virtual bool dirichlet(const IntersectionType& intersection) const
  {
    if (hasDirichlet_ && intersection.boundary()) {
      const IdType boundaryId = intersection.boundaryId();
      // get set of dirichlet ids (has to be found, otherwise hasDirichlet_ would be false)
      const auto result = boundaryInfoMap_.find("dirichlet");
      assert(result != boundaryInfoMap_.end());
      const IdSetType& idSet = result->second;
      return (idSet.count(boundaryId) > 0);
    } else
      return false;
  } // bool dirichlet(const IntersectionType& intersection) const

  virtual bool neumann(const IntersectionType& intersection) const
  {
    if (hasNeumann_ && intersection.boundary()) {
      // get boundary id
      const IdType boundaryId = intersection.boundaryId();
      // get set of neumann ids (has to be found, otherwise hasNeumann_ would be false)
      const typename IdSetMapType::const_iterator result = boundaryInfoMap_.find("neumann");
      assert(result != boundaryInfoMap_.end());
      const IdSetType& idSet = result->second;
      return (idSet.count(boundaryId) > 0);
    } else
      return false;
  } // bool neumann(const IntersectionType& intersection) const

private:

  IdSetMapType  boundaryInfoMap_;
  bool hasDirichlet_;
  bool hasNeumann_;
}; // class GridboundaryIdBased

template< class IntersectionImp >
class GridboundaryNormalBased
  : public GridboundaryInterface< IntersectionImp >
{
  typedef GridboundaryInterface< IntersectionImp >    BaseType;
public:
  typedef GridboundaryNormalBased< IntersectionImp >  ThisType;
  typedef typename BaseType::IntersectionType         IntersectionType;

  typedef typename IntersectionType::ctype DomainFieldType;
  static const unsigned int dimDomain = IntersectionType::dimension;
  typedef Dune::FieldVector< DomainFieldType, dimDomain > DomainType;

  static const std::string id()
  {
    return BaseType::id() + ".normalbased";
  }

  GridboundaryNormalBased(const bool defaultIsDirichlet = true,
                          const std::vector< DomainType > dirichletNormals = std::vector< DomainType >(),
                          const std::vector< DomainType > neumannNormals = std::vector< DomainType >(),
                          const DomainFieldType tol = 1e-10)
    : defaultIsDirichlet_(defaultIsDirichlet)
    , dirichletNormals_(dirichletNormals)
    , neumannNormals_(neumannNormals)
    , tol_(tol)
  {
    normalize();
  }

  GridboundaryNormalBased(const Dune::ParameterTree& _settings, const std::string subName = id())
  {
    const Common::ExtendedParameterTree settings = _settings.hasSub(subName) ? _settings.sub(subName) : _settings;
    const std::string def = settings.get("default", "dirichlet");
    if (def == "dirichlet")
      defaultIsDirichlet_ = true;
    else if(def == "neumann")
      defaultIsDirichlet_ = false;
    else
      DUNE_THROW(Dune::IOError,
                 "\n" << Dune::Stuff::Common::colorStringRed("ERROR:") << " wrong 'default' given!");
    tol_ = settings.get("compare_tolerance", 1e-10);
    dirichletNormals_ = getVectors(settings, "dirichlet");
    neumannNormals_ = getVectors(settings, "neumann");
    normalize();
  }

  static Dune::ParameterTree defaultSettings(const std::string subName = "")
  {
    Dune::ParameterTree description;
    description["default"] = "dirichlet";
    description["compare_tolerance"] = "1e-10";
    description["neumann.0"] = "[1.0; 0.0]";
    description["dirichlet.0"] = "[0.0; 1.0]";
    if (subName.empty())
      return description;
    else {
      Dune::Stuff::Common::ExtendedParameterTree extendedDescription;
      extendedDescription.add(description, subName);
      return extendedDescription;
    }
  }

  static ThisType* create(const Dune::ParameterTree& settings, const std::string subName = id())
  {
    return new ThisType(settings, subName);
  }

  virtual bool dirichlet(const IntersectionType& intersection) const
  {
    if (intersection.boundary()) {
      const DomainType outerNormal = intersection.centerUnitOuterNormal();
      if (contains(outerNormal, dirichletNormals_))
        return true;
      else if (contains(outerNormal, neumannNormals_))
        return false;
      else
        return defaultIsDirichlet_;
    }
    return false;
  } // bool dirichlet(const IntersectionType& intersection) const

  virtual bool neumann(const IntersectionType& intersection) const
  {
    return !dirichlet(intersection);
  } // bool neumann(const IntersectionType& intersection) const

private:
  static std::vector< DomainType > getVectors(const Common::ExtendedParameterTree& paramTree, const std::string key)
  {
    std::vector< DomainType > ret;
    if (paramTree.hasSub(key)) {
      bool found = true;
      unsigned int counter = 0;
      while (found) {
        const std::string localKey = key + "." + Dune::Stuff::Common::toString(counter);
        if (paramTree.hasKey(localKey)) {
          std::vector< DomainFieldType > vec = paramTree.getVector< DomainFieldType >(localKey, dimDomain);
          DomainType fvec(0);
          for (size_t dd = 0; dd < dimDomain; ++dd)
            fvec[dd] = vec[dd];
          ret.push_back(fvec);
        } else
          found = false;
        ++counter;
      }
    } else if (paramTree.hasKey(key)) {
      std::vector< DomainFieldType > vec = paramTree.getVector< DomainFieldType >(key, dimDomain);
      DomainType fvec(0);
      for (size_t dd = 0; dd < dimDomain; ++dd)
        fvec[dd] = vec[dd];
      ret.push_back(fvec);
    }
    return ret;
  }

  bool contains(const DomainType& normal, const std::vector< DomainType >& vectors) const
  {
    for (auto& vector : vectors)
      if (Dune::Stuff::Common::FloatCmp::eq(normal, vector, tol_))
        return true;
    return false;
  }

  void normalize() {
    // normalize
    for (auto& normal : dirichletNormals_)
      normal /= normal.two_norm();
    for (auto& normal : neumannNormals_)
      normal /= normal.two_norm();
    // sanity check
    for (auto& dirichletNormal : dirichletNormals_) {
      if (contains(dirichletNormal, neumannNormals_))
        DUNE_THROW(Dune::InvalidStateException,
                   "\n" << Dune::Stuff::Common::colorStringRed("ERROR:") << " normals are too close!");
    }
  }

  bool defaultIsDirichlet_;
  std::vector< DomainType > dirichletNormals_;
  std::vector< DomainType > neumannNormals_;
  DomainFieldType tol_;
}; // class GridboundaryNormalBased

template< class IntersectionType >
class Gridboundaries
{
public:
  static std::vector< std::string > available()
  {
    return {
        "boundaryinfo.alldirichlet"
      , "boundaryinfo.allneumann"
      , "boundaryinfo.idbased"
      , "boundaryinfo.normalbased"
    };
  } // ... available(...)

  static Dune::ParameterTree defaultSettings(const std::string type, const std::string subname = "")
  {
    if (type == "boundaryinfo.alldirichlet")
      return GridboundaryAllDirichlet< IntersectionType >::defaultSettings(subname);
    else if (type == "boundaryinfo.allneumann")
      return GridboundaryAllNeumann< IntersectionType >::defaultSettings(subname);
    else if (type == "boundaryinfo.idbased")
      return GridboundaryIdBased< IntersectionType >::defaultSettings(subname);
    else if (type == "boundaryinfo.normalbased")
      return GridboundaryNormalBased< IntersectionType >::defaultSettings(subname);
    else
      DUNE_THROW(Dune::RangeError,
                 "\n" << Dune::Stuff::Common::colorStringRed("ERROR:")
                 << " unknown boundaryinfo '" << type << "' requested!");
  } // ... createDefaultSettings(...)

  static GridboundaryInterface< IntersectionType >* create(const std::string& type = available()[0],
                                                           const Dune::ParameterTree settings = Dune::ParameterTree())
  {
    if (type == "boundaryinfo.alldirichlet") {
      return new GridboundaryAllDirichlet< IntersectionType >();
    } else if (type == "boundaryinfo.allneumann") {
      return new GridboundaryAllNeumann< IntersectionType >();
    } else if (type == "boundaryinfo.idbased") {
      return GridboundaryIdBased< IntersectionType >::create(settings);
    } else if (type == "boundaryinfo.normalbased") {
      return GridboundaryNormalBased< IntersectionType >::create(settings);
    } else
      DUNE_THROW(Dune::RangeError,
                 "\n" << Dune::Stuff::Common::colorStringRed("ERROR:")
                 << " unknown boundaryinfo '" << type << "' requested!");
  } // ... create(...)
}; // class Gridboundaries

} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_GRID_BOUNDARYINFO_HH
<commit_msg>Revert "[grid] no longer accept a shread_ptr in GridboundaryIdBased ctor"<commit_after>// This file is part of the dune-stuff project:
//   http://users.dune-project.org/projects/dune-stuff/
// Copyright Holders: Felix Albrecht, Rene Milk
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_GRID_BOUNDARYINFO_HH
#define DUNE_STUFF_GRID_BOUNDARYINFO_HH

#include <map>
#include <set>
#include <string>
#include <vector>
#include <memory>

#include <dune/common/exceptions.hh>
#include <dune/common/fvector.hh>

#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/color.hh>
#include <dune/stuff/common/vector.hh>
#include <dune/stuff/common/float_cmp.hh>

namespace Dune {
namespace Stuff {

template< class IntersectionImp >
class GridboundaryInterface
{
public:
  typedef IntersectionImp IntersectionType;

  static const std::string id()
  {
    return "boundaryinfo";
  }

  virtual ~GridboundaryInterface() {}

  virtual bool dirichlet(const IntersectionType&) const = 0;

  virtual bool neumann(const IntersectionType&) const = 0;
}; // class GridboundaryInterface

template< class IntersectionImp >
class GridboundaryAllDirichlet
  : public GridboundaryInterface< IntersectionImp >
{
  typedef GridboundaryInterface< IntersectionImp >  BaseType;
public:
  typedef typename BaseType::IntersectionType       IntersectionType;

  static const std::string id()
  {
    return BaseType::id() + ".alldirichlet";
  }

  static Dune::ParameterTree defaultSettings(const std::string /*subName*/ = "")
  {
    return Dune::ParameterTree();
  }

  GridboundaryAllDirichlet() {}

  virtual bool dirichlet(const IntersectionType& intersection) const
  {
    if (intersection.boundary())
      return true;
    else
      return false;
  } // virtual bool dirichlet(const IntersectionType& intersection) const

  virtual bool neumann(const IntersectionType&) const
  {
    return false;
  }
}; // class GridboundaryAllDirichlet

template< class IntersectionImp >
class GridboundaryAllNeumann
  : public GridboundaryInterface< IntersectionImp >
{
  typedef GridboundaryInterface< IntersectionImp >  BaseType;
public:
  typedef typename BaseType::IntersectionType       IntersectionType;

  static const std::string id()
  {
    return BaseType::id() + ".allneumann";
  }

  static Dune::ParameterTree defaultSettings(const std::string /*subName*/ = "")
  {
    return Dune::ParameterTree();
  }

  GridboundaryAllNeumann() {}

  virtual bool dirichlet(const IntersectionType& /*intersection*/) const
  {
    return false;
  }

  virtual bool neumann(const IntersectionType& intersection) const
  {
    return intersection.boundary();
  } // virtual bool neumann(const IntersectionType& intersection) const
}; // class GridboundaryAllNeumann

template< class IntersectionImp >
class GridboundaryIdBased
  : public GridboundaryInterface< IntersectionImp >
{
  typedef GridboundaryInterface< IntersectionImp >  BaseType;
public:
  typedef GridboundaryIdBased< IntersectionImp >    ThisType;
  typedef typename BaseType::IntersectionType       IntersectionType;

  static const std::string id()
  {
    return BaseType::id() + ".idbased";
  }

  typedef int                                 IdType;
  typedef std::set< IdType >                  IdSetType;
  typedef std::map< std::string, IdSetType >  IdSetMapType;

  GridboundaryIdBased(const std::shared_ptr< const IdSetMapType > boundaryInfoMap)
      : boundaryInfoMap_(*boundaryInfoMap)
      , hasDirichlet_(boundaryInfoMap_.find("dirichlet") != boundaryInfoMap_.end())
      , hasNeumann_(boundaryInfoMap_.find("neumann") != boundaryInfoMap_.end())
  {}

  GridboundaryIdBased(const Dune::ParameterTree& settings, const std::string subName = id())
  {
    const Common::ExtendedParameterTree ext_settings = settings.hasSub(subName) ? settings.sub(subName) : settings;
    const std::vector< int > dirichletIds = ext_settings.getVector< int >("dirichlet", 0, 0);
    const std::vector< int > neumannIds = ext_settings.getVector< int >("neumann", 0, 0);
    boundaryInfoMap_.insert(std::pair< std::string, IdSetType >("dirichlet", IdSetType(dirichletIds.begin(), dirichletIds.end())));
    boundaryInfoMap_.emplace("neumann", IdSetType(neumannIds.begin(), neumannIds.end()));
    hasDirichlet_ = boundaryInfoMap_.find("dirichlet") != boundaryInfoMap_.end();
    hasNeumann_ = boundaryInfoMap_.find("neumann") != boundaryInfoMap_.end();
  }

  static Dune::ParameterTree defaultSettings(const std::string subName = "")
  {
    Dune::ParameterTree description;
    description["dirichlet"] = "[1; 2; 3]";
    description["neumann"] = "[4]";
    if (subName.empty())
      return description;
    else {
      Dune::Stuff::Common::ExtendedParameterTree extendedDescription;
      extendedDescription.add(description, subName);
      return extendedDescription;
    }
  }

  static ThisType* create(const Dune::ParameterTree& settings, const std::string subName = id()) {
    return new ThisType(settings, subName);
  }

  const IdSetMapType& boundaryInfoMap() const
  {
    return boundaryInfoMap_;
  }

  virtual bool dirichlet(const IntersectionType& intersection) const
  {
    if (hasDirichlet_ && intersection.boundary()) {
      const IdType boundaryId = intersection.boundaryId();
      // get set of dirichlet ids (has to be found, otherwise hasDirichlet_ would be false)
      const auto result = boundaryInfoMap_.find("dirichlet");
      assert(result != boundaryInfoMap_.end());
      const IdSetType& idSet = result->second;
      return (idSet.count(boundaryId) > 0);
    } else
      return false;
  } // bool dirichlet(const IntersectionType& intersection) const

  virtual bool neumann(const IntersectionType& intersection) const
  {
    if (hasNeumann_ && intersection.boundary()) {
      // get boundary id
      const IdType boundaryId = intersection.boundaryId();
      // get set of neumann ids (has to be found, otherwise hasNeumann_ would be false)
      const typename IdSetMapType::const_iterator result = boundaryInfoMap_.find("neumann");
      assert(result != boundaryInfoMap_.end());
      const IdSetType& idSet = result->second;
      return (idSet.count(boundaryId) > 0);
    } else
      return false;
  } // bool neumann(const IntersectionType& intersection) const

private:

  IdSetMapType  boundaryInfoMap_;
  bool hasDirichlet_;
  bool hasNeumann_;
}; // class GridboundaryIdBased

template< class IntersectionImp >
class GridboundaryNormalBased
  : public GridboundaryInterface< IntersectionImp >
{
  typedef GridboundaryInterface< IntersectionImp >    BaseType;
public:
  typedef GridboundaryNormalBased< IntersectionImp >  ThisType;
  typedef typename BaseType::IntersectionType         IntersectionType;

  typedef typename IntersectionType::ctype DomainFieldType;
  static const unsigned int dimDomain = IntersectionType::dimension;
  typedef Dune::FieldVector< DomainFieldType, dimDomain > DomainType;

  static const std::string id()
  {
    return BaseType::id() + ".normalbased";
  }

  GridboundaryNormalBased(const bool defaultIsDirichlet = true,
                          const std::vector< DomainType > dirichletNormals = std::vector< DomainType >(),
                          const std::vector< DomainType > neumannNormals = std::vector< DomainType >(),
                          const DomainFieldType tol = 1e-10)
    : defaultIsDirichlet_(defaultIsDirichlet)
    , dirichletNormals_(dirichletNormals)
    , neumannNormals_(neumannNormals)
    , tol_(tol)
  {
    normalize();
  }

  GridboundaryNormalBased(const Dune::ParameterTree& _settings, const std::string subName = id())
  {
    const Common::ExtendedParameterTree settings = _settings.hasSub(subName) ? _settings.sub(subName) : _settings;
    const std::string def = settings.get("default", "dirichlet");
    if (def == "dirichlet")
      defaultIsDirichlet_ = true;
    else if(def == "neumann")
      defaultIsDirichlet_ = false;
    else
      DUNE_THROW(Dune::IOError,
                 "\n" << Dune::Stuff::Common::colorStringRed("ERROR:") << " wrong 'default' given!");
    tol_ = settings.get("compare_tolerance", 1e-10);
    dirichletNormals_ = getVectors(settings, "dirichlet");
    neumannNormals_ = getVectors(settings, "neumann");
    normalize();
  }

  static Dune::ParameterTree defaultSettings(const std::string subName = "")
  {
    Dune::ParameterTree description;
    description["default"] = "dirichlet";
    description["compare_tolerance"] = "1e-10";
    description["neumann.0"] = "[1.0; 0.0]";
    description["dirichlet.0"] = "[0.0; 1.0]";
    if (subName.empty())
      return description;
    else {
      Dune::Stuff::Common::ExtendedParameterTree extendedDescription;
      extendedDescription.add(description, subName);
      return extendedDescription;
    }
  }

  static ThisType* create(const Dune::ParameterTree& settings, const std::string subName = id())
  {
    return new ThisType(settings, subName);
  }

  virtual bool dirichlet(const IntersectionType& intersection) const
  {
    if (intersection.boundary()) {
      const DomainType outerNormal = intersection.centerUnitOuterNormal();
      if (contains(outerNormal, dirichletNormals_))
        return true;
      else if (contains(outerNormal, neumannNormals_))
        return false;
      else
        return defaultIsDirichlet_;
    }
    return false;
  } // bool dirichlet(const IntersectionType& intersection) const

  virtual bool neumann(const IntersectionType& intersection) const
  {
    return !dirichlet(intersection);
  } // bool neumann(const IntersectionType& intersection) const

private:
  static std::vector< DomainType > getVectors(const Common::ExtendedParameterTree& paramTree, const std::string key)
  {
    std::vector< DomainType > ret;
    if (paramTree.hasSub(key)) {
      bool found = true;
      unsigned int counter = 0;
      while (found) {
        const std::string localKey = key + "." + Dune::Stuff::Common::toString(counter);
        if (paramTree.hasKey(localKey)) {
          std::vector< DomainFieldType > vec = paramTree.getVector< DomainFieldType >(localKey, dimDomain);
          DomainType fvec(0);
          for (size_t dd = 0; dd < dimDomain; ++dd)
            fvec[dd] = vec[dd];
          ret.push_back(fvec);
        } else
          found = false;
        ++counter;
      }
    } else if (paramTree.hasKey(key)) {
      std::vector< DomainFieldType > vec = paramTree.getVector< DomainFieldType >(key, dimDomain);
      DomainType fvec(0);
      for (size_t dd = 0; dd < dimDomain; ++dd)
        fvec[dd] = vec[dd];
      ret.push_back(fvec);
    }
    return ret;
  }

  bool contains(const DomainType& normal, const std::vector< DomainType >& vectors) const
  {
    for (auto& vector : vectors)
      if (Dune::Stuff::Common::FloatCmp::eq(normal, vector, tol_))
        return true;
    return false;
  }

  void normalize() {
    // normalize
    for (auto& normal : dirichletNormals_)
      normal /= normal.two_norm();
    for (auto& normal : neumannNormals_)
      normal /= normal.two_norm();
    // sanity check
    for (auto& dirichletNormal : dirichletNormals_) {
      if (contains(dirichletNormal, neumannNormals_))
        DUNE_THROW(Dune::InvalidStateException,
                   "\n" << Dune::Stuff::Common::colorStringRed("ERROR:") << " normals are too close!");
    }
  }

  bool defaultIsDirichlet_;
  std::vector< DomainType > dirichletNormals_;
  std::vector< DomainType > neumannNormals_;
  DomainFieldType tol_;
}; // class GridboundaryNormalBased

template< class IntersectionType >
class Gridboundaries
{
public:
  static std::vector< std::string > available()
  {
    return {
        "boundaryinfo.alldirichlet"
      , "boundaryinfo.allneumann"
      , "boundaryinfo.idbased"
      , "boundaryinfo.normalbased"
    };
  } // ... available(...)

  static Dune::ParameterTree defaultSettings(const std::string type, const std::string subname = "")
  {
    if (type == "boundaryinfo.alldirichlet")
      return GridboundaryAllDirichlet< IntersectionType >::defaultSettings(subname);
    else if (type == "boundaryinfo.allneumann")
      return GridboundaryAllNeumann< IntersectionType >::defaultSettings(subname);
    else if (type == "boundaryinfo.idbased")
      return GridboundaryIdBased< IntersectionType >::defaultSettings(subname);
    else if (type == "boundaryinfo.normalbased")
      return GridboundaryNormalBased< IntersectionType >::defaultSettings(subname);
    else
      DUNE_THROW(Dune::RangeError,
                 "\n" << Dune::Stuff::Common::colorStringRed("ERROR:")
                 << " unknown boundaryinfo '" << type << "' requested!");
  } // ... createDefaultSettings(...)

  static GridboundaryInterface< IntersectionType >* create(const std::string& type = available()[0],
                                                           const Dune::ParameterTree settings = Dune::ParameterTree())
  {
    if (type == "boundaryinfo.alldirichlet") {
      return new GridboundaryAllDirichlet< IntersectionType >();
    } else if (type == "boundaryinfo.allneumann") {
      return new GridboundaryAllNeumann< IntersectionType >();
    } else if (type == "boundaryinfo.idbased") {
      return GridboundaryIdBased< IntersectionType >::create(settings);
    } else if (type == "boundaryinfo.normalbased") {
      return GridboundaryNormalBased< IntersectionType >::create(settings);
    } else
      DUNE_THROW(Dune::RangeError,
                 "\n" << Dune::Stuff::Common::colorStringRed("ERROR:")
                 << " unknown boundaryinfo '" << type << "' requested!");
  } // ... create(...)
}; // class Gridboundaries

} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_GRID_BOUNDARYINFO_HH
<|endoftext|>


<commit_before>#include "YuleRand.h"

YuleRand::YuleRand(double shape)
{
    setShape(shape);
}

std::string YuleRand::name()
{
    return "Yule(" + toStringWithPrecision(getShape()) + ")";
}

void YuleRand::setShape(double shape)
{
    ro = shape;
    if (ro <= 0)
        ro = MIN_POSITIVE;
    gamma1pRo = std::tgamma(ro + 1);
}

double YuleRand::P(int k) const
{
    return (k < 1) ? 0 : ro * gamma1pRo * std::tgamma(k) / std::tgamma(k + ro + 1);
}

double YuleRand::F(double x) const
{
    if (x < 1)
        return 0;
    double k = std::floor(x);
    return 1 - k * gamma1pRo * std::tgamma(k) / std::tgamma(k + ro + 1);
}

double YuleRand::variate() const
{
    return YuleRand::variate(ro);
}

double YuleRand::variate(double shape)
{
    double prob = 1.0 / ParetoRand::variate(shape, 1.0);
    return GeometricRand::variate(prob) + 1;
}

double YuleRand::Mean() const
{
    return (ro <= 1) ? INFINITY : ro / (ro - 1);
}

double YuleRand::Variance() const
{
    if (ro <= 2)
        return INFINITY;
    double aux = ro / (ro - 1);
    return aux * aux / (ro - 2);
}

double YuleRand::Mode() const
{
    return 1.0;
}

double YuleRand::Skewness() const
{
    if (ro <= 3)
        return INFINITY;
    double skewness = ro + 1;
    skewness *= skewness;
    skewness *= std::sqrt(ro - 2);
    return skewness / (ro * (ro - 3));
}

double YuleRand::ExcessKurtosis() const
{
    if (ro <= 4)
        return INFINITY;
    double numerator = 11 * ro * ro - 49;
    numerator *= ro;
    numerator -= 22;
    double denominator = ro * (ro - 4) * (ro - 3);
    return ro + 3 + numerator / denominator;
}
<commit_msg>Update YuleRand.cpp<commit_after>#include "YuleRand.h"

YuleRand::YuleRand(double shape) :
X(shape, 1.0)
{
    setShape(shape);
}

std::string YuleRand::name()
{
    return "Yule(" + toStringWithPrecision(getShape()) + ")";
}

void YuleRand::setShape(double shape)
{
    ro = shape;
    if (ro <= 0)
        ro = MIN_POSITIVE;
    gamma1pRo = std::tgamma(ro + 1);
    X.setShape(ro);
}

double YuleRand::P(int k) const
{
    return (k < 1) ? 0 : ro * gamma1pRo * std::tgamma(k) / std::tgamma(k + ro + 1);
}

double YuleRand::F(double x) const
{
    if (x < 1)
        return 0;
    double k = std::floor(x);
    return 1 - k * gamma1pRo * std::tgamma(k) / std::tgamma(k + ro + 1);
}

double YuleRand::variate() const
{
    double prob = 1.0 / X.variate();
    return GeometricRand::variate(prob) + 1;
}

double YuleRand::variate(double shape)
{
    double prob = 1.0 / ParetoRand::variate(shape, 1.0);
    return GeometricRand::variate(prob) + 1;
}

void YuleRand::sample(QVector<double> &outputData) const
{
    X.sample(outputData);
    for (double & var : outputData)
        var = GeometricRand::variate(1.0 / var) + 1;
}

double YuleRand::Mean() const
{
    return (ro <= 1) ? INFINITY : ro / (ro - 1);
}

double YuleRand::Variance() const
{
    if (ro <= 2)
        return INFINITY;
    double aux = ro / (ro - 1);
    return aux * aux / (ro - 2);
}

double YuleRand::Mode() const
{
    return 1.0;
}

double YuleRand::Skewness() const
{
    if (ro <= 3)
        return INFINITY;
    double skewness = ro + 1;
    skewness *= skewness;
    skewness *= std::sqrt(ro - 2);
    return skewness / (ro * (ro - 3));
}

double YuleRand::ExcessKurtosis() const
{
    if (ro <= 4)
        return INFINITY;
    double numerator = 11 * ro * ro - 49;
    numerator *= ro;
    numerator -= 22;
    double denominator = ro * (ro - 4) * (ro - 3);
    return ro + 3 + numerator / denominator;
}
<|endoftext|>