<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbDisparityMapToDEMFilter.h"
#include "otbWrapperElevationParametersHandler.h"

#include "otbImageList.h"
#include "otbVectorImageToImageListFilter.h"

namespace otb
{
namespace Wrapper
{

class DisparityMapToElevationMap : public Application
{
public:
  /** Standard class typedefs. */
  typedef DisparityMapToElevationMap    Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  typedef otb::ImageList<FloatImageType>                  ImageListType;
  typedef otb::VectorImageToImageListFilter
    <FloatVectorImageType, ImageListType>                 VectorImageToListFilterType;

  typedef otb::DisparityMapToDEMFilter
    <FloatImageType, FloatVectorImageType>                DisparityToElevationFilterType;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(DisparityMapToElevationMap, otb::Application);

  /** Filters typedef */

private:
  DisparityMapToElevationMap()
  {
    // Initialize filters
    m_VectorToList = VectorImageToListFilterType::New();
    m_DispToElev = DisparityToElevationFilterType::New();
  }

  void DoInit()
  {
    SetName("DisparityMapToElevationMap");
    SetDescription("Projects a disparity map into a regular elevation map");

    SetDocName("Disparity map to elevation map");
    SetDocLongDescription("This application uses a disparity map computed from a stereo image pair to produce an "
      "elevation map on the ground area covered by the stereo pair. The needed inputs are : the disparity map, "
      "the stereo pair (in original geometry) and the epipolar deformation grids. These grids have to link the "
      "original geometry (stereo pair) and the epipolar geometry (disparity map). ");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso("otbStereoRectificationGridGenerator otbBlockMatching");

    AddDocTag(Tags::Stereo);

    AddParameter(ParameterType_InputImage,"in","Input disparity map");
    SetParameterDescription("in","The input disparity map (horizontal disparity in first band, vertical in second)");

    AddParameter(ParameterType_InputImage,"left","Left sensor image");
    SetParameterDescription("left","Left image in original (sensor) geometry");

    AddParameter(ParameterType_InputImage,"right","Right sensor image");
    SetParameterDescription("right","Right image in original (sensor) geometry");

    AddParameter(ParameterType_InputImage,"lgrid","Left Grid");
    SetParameterDescription("lgrid","Left epipolar grid (deformation grid between sensor et disparity spaces)");

    AddParameter(ParameterType_InputImage,"rgrid","Right Grid");
    SetParameterDescription("rgrid","Right epipolar grid (deformation grid between sensor et disparity spaces)");

    AddParameter(ParameterType_OutputImage,"out","Output elevation map");
    SetParameterDescription("out", "Output elevation map in ground projection");

    AddParameter(ParameterType_Float,"step","DEM step");
    SetParameterDescription("step","Spacing of the output elevation map (in meters)");
    SetDefaultParameterFloat("step",5.0);

    AddParameter(ParameterType_Float,"hmin","Minimum elevation expected");
    SetParameterDescription("hmin","Minimum elevation expected (in meters)");
    SetDefaultParameterFloat("hmin",0.0);

    AddParameter(ParameterType_Float,"hmax","Maximum elevation expected");
    SetParameterDescription("hmax","Maximum elevation expected (in meters)");
    SetDefaultParameterFloat("hmax",100.0);

    AddParameter(ParameterType_InputImage,"mask","Disparity mask");
    SetParameterDescription("mask","Masked disparity cells won't be projected");
    MandatoryOff("mask");

    ElevationParametersHandler::AddElevationParameters(this, "elev");

    AddRAMParameter();

    // Doc example parameter settings
    SetDocExampleParameterValue("in","disparity.tif");
    SetDocExampleParameterValue("left","sensor_left.tif");
    SetDocExampleParameterValue("right","sensor_right.tif");
    SetDocExampleParameterValue("lgrid","grid_epi_left.tif");
    SetDocExampleParameterValue("rgrid","grid_epi_right.tif");
    SetDocExampleParameterValue("out","dem.tif");
  }

  void DoUpdateParameters()
  {
    // Nothing to do
  }

  void DoExecute()
  {
    FloatVectorImageType::Pointer inputDisp     = this->GetParameterImage("in");
    FloatVectorImageType::Pointer sensorLeft    = this->GetParameterImage("left");
    FloatVectorImageType::Pointer sensorRight   = this->GetParameterImage("right");
    FloatVectorImageType::Pointer gridLeft      = this->GetParameterImage("lgrid");
    FloatVectorImageType::Pointer gridRight     = this->GetParameterImage("rgrid");

    m_VectorToList->SetInput(inputDisp);
    m_VectorToList->UpdateOutputInformation();

    m_DispToElev->SetHorizontalDisparityMapInput(m_VectorToList->GetOutput()->GetNthElement(0));
    m_DispToElev->SetVerticalDisparityMapInput(m_VectorToList->GetOutput()->GetNthElement(1));
    m_DispToElev->SetLeftInput(sensorLeft);
    m_DispToElev->SetRightInput(sensorRight);
    m_DispToElev->SetLeftEpipolarGridInput(gridLeft);
    m_DispToElev->SetRightEpipolarGridInput(gridRight);
    m_DispToElev->SetElevationMin(this->GetParameterFloat("hmin"));
    m_DispToElev->SetElevationMax(this->GetParameterFloat("hmax"));
    m_DispToElev->SetDEMGridStep(this->GetParameterFloat("step"));

    if (IsParameterEnabled("mask"))
      {
      m_DispToElev->SetDisparityMaskInput(this->GetParameterUInt8Image("mask"));
      }

    if (ElevationParametersHandler::IsElevationEnabled(this, "elev"))
      {
      switch(ElevationParametersHandler::GetElevationType(this, "elev"))
        {
        case Elevation_DEM:
        {
        m_DispToElev->SetDEMDirectory(ElevationParametersHandler::GetDEMDirectory(this, "elev"));
        m_DispToElev->SetGeoidFile(ElevationParametersHandler::GetGeoidFile(this, "elev"));
        }
        break;
        case Elevation_Average:
        {
        m_DispToElev->SetAverageElevation(ElevationParametersHandler::GetAverageElevation(this, "elev"));
        }
        break;
        }
      }

    this->SetParameterOutputImage("out",m_DispToElev->GetOutput());
  }

  VectorImageToListFilterType::Pointer m_VectorToList;

  DisparityToElevationFilterType::Pointer m_DispToElev;
};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::DisparityMapToElevationMap)
<commit_msg>ENH:add a group parameter for IO in DisparityMapToElevation<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"

#include "otbDisparityMapToDEMFilter.h"
#include "otbWrapperElevationParametersHandler.h"

#include "otbImageList.h"
#include "otbVectorImageToImageListFilter.h"

namespace otb
{
namespace Wrapper
{

class DisparityMapToElevationMap : public Application
{
public:
  /** Standard class typedefs. */
  typedef DisparityMapToElevationMap    Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  typedef otb::ImageList<FloatImageType>                  ImageListType;
  typedef otb::VectorImageToImageListFilter
    <FloatVectorImageType, ImageListType>                 VectorImageToListFilterType;

  typedef otb::DisparityMapToDEMFilter
    <FloatImageType, FloatVectorImageType>                DisparityToElevationFilterType;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(DisparityMapToElevationMap, otb::Application);

  /** Filters typedef */

private:
  DisparityMapToElevationMap()
  {
    // Initialize filters
    m_VectorToList = VectorImageToListFilterType::New();
    m_DispToElev = DisparityToElevationFilterType::New();
  }

  void DoInit()
  {
    SetName("DisparityMapToElevationMap");
    SetDescription("Projects a disparity map into a regular elevation map");

    SetDocName("Disparity map to elevation map");
    SetDocLongDescription("This application uses a disparity map computed from a stereo image pair to produce an "
      "elevation map on the ground area covered by the stereo pair. The needed inputs are : the disparity map, "
      "the stereo pair (in original geometry) and the epipolar deformation grids. These grids have to link the "
      "original geometry (stereo pair) and the epipolar geometry (disparity map). ");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso("otbStereoRectificationGridGenerator otbBlockMatching");

    AddDocTag(Tags::Stereo);

    AddParameter(ParameterType_Group,"io","Input and output data");
    SetParameterDescription("io","This group of parameters allows to set the input and output images and grids.");

    AddParameter(ParameterType_InputImage,"io.in","Input disparity map");
    SetParameterDescription("io.in","The input disparity map (horizontal disparity in first band, vertical in second)");

    AddParameter(ParameterType_InputImage,"io.left","Left sensor image");
    SetParameterDescription("io.left","Left image in original (sensor) geometry");

    AddParameter(ParameterType_InputImage,"io.right","Right sensor image");
    SetParameterDescription("io.right","Right image in original (sensor) geometry");

    AddParameter(ParameterType_InputImage,"io.lgrid","Left Grid");
    SetParameterDescription("io.lgrid","Left epipolar grid (deformation grid between sensor et disparity spaces)");

    AddParameter(ParameterType_InputImage,"io.rgrid","Right Grid");
    SetParameterDescription("io.rgrid","Right epipolar grid (deformation grid between sensor et disparity spaces)");

    AddParameter(ParameterType_OutputImage,"io.out","Output elevation map");
    SetParameterDescription("io.out", "Output elevation map in ground projection");

    AddParameter(ParameterType_Float,"step","DEM step");
    SetParameterDescription("step","Spacing of the output elevation map (in meters)");
    SetDefaultParameterFloat("step",5.0);

    AddParameter(ParameterType_Float,"hmin","Minimum elevation expected");
    SetParameterDescription("hmin","Minimum elevation expected (in meters)");
    SetDefaultParameterFloat("hmin",0.0);

    AddParameter(ParameterType_Float,"hmax","Maximum elevation expected");
    SetParameterDescription("hmax","Maximum elevation expected (in meters)");
    SetDefaultParameterFloat("hmax",100.0);

    AddParameter(ParameterType_InputImage,"io.mask","Disparity mask");
    SetParameterDescription("io.mask","Masked disparity cells won't be projected");
    MandatoryOff("io.mask");

    ElevationParametersHandler::AddElevationParameters(this, "elev");

    AddRAMParameter();

    // Doc example parameter settings
    SetDocExampleParameterValue("io.in","disparity.tif");
    SetDocExampleParameterValue("io.left","sensor_left.tif");
    SetDocExampleParameterValue("io.right","sensor_right.tif");
    SetDocExampleParameterValue("io.lgrid","grid_epi_left.tif");
    SetDocExampleParameterValue("io.rgrid","grid_epi_right.tif");
    SetDocExampleParameterValue("io.out","dem.tif");
  }

  void DoUpdateParameters()
  {
    // Nothing to do
  }

  void DoExecute()
  {
    FloatVectorImageType::Pointer inputDisp     = this->GetParameterImage("io.in");
    FloatVectorImageType::Pointer sensorLeft    = this->GetParameterImage("io.left");
    FloatVectorImageType::Pointer sensorRight   = this->GetParameterImage("io.right");
    FloatVectorImageType::Pointer gridLeft      = this->GetParameterImage("io.lgrid");
    FloatVectorImageType::Pointer gridRight     = this->GetParameterImage("io.rgrid");

    m_VectorToList->SetInput(inputDisp);
    m_VectorToList->UpdateOutputInformation();

    m_DispToElev->SetHorizontalDisparityMapInput(m_VectorToList->GetOutput()->GetNthElement(0));
    m_DispToElev->SetVerticalDisparityMapInput(m_VectorToList->GetOutput()->GetNthElement(1));
    m_DispToElev->SetLeftInput(sensorLeft);
    m_DispToElev->SetRightInput(sensorRight);
    m_DispToElev->SetLeftEpipolarGridInput(gridLeft);
    m_DispToElev->SetRightEpipolarGridInput(gridRight);
    m_DispToElev->SetElevationMin(this->GetParameterFloat("hmin"));
    m_DispToElev->SetElevationMax(this->GetParameterFloat("hmax"));
    m_DispToElev->SetDEMGridStep(this->GetParameterFloat("step"));

    if (IsParameterEnabled("io.mask"))
      {
      m_DispToElev->SetDisparityMaskInput(this->GetParameterUInt8Image("io.mask"));
      }

    if (ElevationParametersHandler::IsElevationEnabled(this, "elev"))
      {
      switch(ElevationParametersHandler::GetElevationType(this, "elev"))
        {
        case Elevation_DEM:
        {
        m_DispToElev->SetDEMDirectory(ElevationParametersHandler::GetDEMDirectory(this, "elev"));
        m_DispToElev->SetGeoidFile(ElevationParametersHandler::GetGeoidFile(this, "elev"));
        }
        break;
        case Elevation_Average:
        {
        m_DispToElev->SetAverageElevation(ElevationParametersHandler::GetAverageElevation(this, "elev"));
        }
        break;
        }
      }

    this->SetParameterOutputImage("io.out",m_DispToElev->GetOutput());
  }

  VectorImageToListFilterType::Pointer m_VectorToList;

  DisparityToElevationFilterType::Pointer m_DispToElev;
};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::DisparityMapToElevationMap)
<|endoftext|>


<commit_before>//===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the MemoryBuffer interface.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/MemoryBuffer.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/system_error.h"
#include <cassert>
#include <cstdio>
#include <cstring>
#include <cerrno>
#include <new>
#include <sys/types.h>
#include <sys/stat.h>
#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
#include <sys/uio.h>
#else
#include <io.h>
#endif
#include <fcntl.h>
using namespace llvm;

namespace { const llvm::error_code success; }

//===----------------------------------------------------------------------===//
// MemoryBuffer implementation itself.
//===----------------------------------------------------------------------===//

MemoryBuffer::~MemoryBuffer() { }

/// init - Initialize this MemoryBuffer as a reference to externally allocated
/// memory, memory that we know is already null terminated.
void MemoryBuffer::init(const char *BufStart, const char *BufEnd,
                        bool RequiresNullTerminator) {
  assert((BufEnd[0] == 0 || !RequiresNullTerminator) &&
         "Buffer is not null terminated!");
  BufferStart = BufStart;
  BufferEnd = BufEnd;
}

//===----------------------------------------------------------------------===//
// MemoryBufferMem implementation.
//===----------------------------------------------------------------------===//

/// CopyStringRef - Copies contents of a StringRef into a block of memory and
/// null-terminates it.
static void CopyStringRef(char *Memory, StringRef Data) {
  memcpy(Memory, Data.data(), Data.size());
  Memory[Data.size()] = 0; // Null terminate string.
}

/// GetNamedBuffer - Allocates a new MemoryBuffer with Name copied after it.
template <typename T>
static T* GetNamedBuffer(StringRef Buffer, StringRef Name,
                         bool RequiresNullTerminator) {
  char *Mem = static_cast<char*>(operator new(sizeof(T) + Name.size() + 1));
  CopyStringRef(Mem + sizeof(T), Name);
  return new (Mem) T(Buffer, RequiresNullTerminator);
}

namespace {
/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
class MemoryBufferMem : public MemoryBuffer {
public:
  MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
    init(InputData.begin(), InputData.end(), RequiresNullTerminator);
  }

  virtual const char *getBufferIdentifier() const {
     // The name is stored after the class itself.
    return reinterpret_cast<const char*>(this + 1);
  }
};
}

/// getMemBuffer - Open the specified memory range as a MemoryBuffer.  Note
/// that EndPtr[0] must be a null byte and be accessible!
MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData,
                                         StringRef BufferName,
                                         bool RequiresNullTerminator) {
  return GetNamedBuffer<MemoryBufferMem>(InputData, BufferName,
                                         RequiresNullTerminator);
}

/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
/// copying the contents and taking ownership of it.  This has no requirements
/// on EndPtr[0].
MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData,
                                             StringRef BufferName) {
  MemoryBuffer *Buf = getNewUninitMemBuffer(InputData.size(), BufferName);
  if (!Buf) return 0;
  memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(),
         InputData.size());
  return Buf;
}

/// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size
/// that is not initialized.  Note that the caller should initialize the
/// memory allocated by this method.  The memory is owned by the MemoryBuffer
/// object.
MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size,
                                                  StringRef BufferName) {
  // Allocate space for the MemoryBuffer, the data and the name. It is important
  // that MemoryBuffer and data are aligned so PointerIntPair works with them.
  size_t AlignedStringLen =
    RoundUpToAlignment(sizeof(MemoryBufferMem) + BufferName.size() + 1,
                       sizeof(void*)); // TODO: Is sizeof(void*) enough?
  size_t RealLen = AlignedStringLen + Size + 1;
  char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow));
  if (!Mem) return 0;

  // The name is stored after the class itself.
  CopyStringRef(Mem + sizeof(MemoryBufferMem), BufferName);

  // The buffer begins after the name and must be aligned.
  char *Buf = Mem + AlignedStringLen;
  Buf[Size] = 0; // Null terminate buffer.

  return new (Mem) MemoryBufferMem(StringRef(Buf, Size), true);
}

/// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that
/// is completely initialized to zeros.  Note that the caller should
/// initialize the memory allocated by this method.  The memory is owned by
/// the MemoryBuffer object.
MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) {
  MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName);
  if (!SB) return 0;
  memset(const_cast<char*>(SB->getBufferStart()), 0, Size);
  return SB;
}

/// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin
/// if the Filename is "-".  If an error occurs, this returns null and fills
/// in *ErrStr with a reason.  If stdin is empty, this API (unlike getSTDIN)
/// returns an empty buffer.
error_code MemoryBuffer::getFileOrSTDIN(StringRef Filename,
                                        OwningPtr<MemoryBuffer> &result,
                                        int64_t FileSize) {
  if (Filename == "-")
    return getSTDIN(result);
  return getFile(Filename, result, FileSize);
}

error_code MemoryBuffer::getFileOrSTDIN(const char *Filename,
                                        OwningPtr<MemoryBuffer> &result,
                                        int64_t FileSize) {
  if (strcmp(Filename, "-") == 0)
    return getSTDIN(result);
  return getFile(Filename, result, FileSize);
}

//===----------------------------------------------------------------------===//
// MemoryBuffer::getFile implementation.
//===----------------------------------------------------------------------===//

namespace {
/// MemoryBufferMMapFile - This represents a file that was mapped in with the
/// sys::Path::MapInFilePages method.  When destroyed, it calls the
/// sys::Path::UnMapFilePages method.
class MemoryBufferMMapFile : public MemoryBufferMem {
public:
  MemoryBufferMMapFile(StringRef Buffer, bool RequiresNullTerminator)
    : MemoryBufferMem(Buffer, RequiresNullTerminator) { }

  ~MemoryBufferMMapFile() {
    static int PageSize = sys::Process::GetPageSize();

    uintptr_t Start = reinterpret_cast<uintptr_t>(getBufferStart());
    size_t Size = getBufferSize();
    uintptr_t RealStart = Start & ~(PageSize - 1);
    size_t RealSize = Size + (Start - RealStart);

    sys::Path::UnMapFilePages(reinterpret_cast<const char*>(RealStart),
                              RealSize);
  }
};
}

error_code MemoryBuffer::getFile(StringRef Filename,
                                 OwningPtr<MemoryBuffer> &result,
                                 int64_t FileSize) {
  // Ensure the path is null terminated.
  SmallString<256> PathBuf(Filename.begin(), Filename.end());
  return MemoryBuffer::getFile(PathBuf.c_str(), result, FileSize);
}

error_code MemoryBuffer::getFile(const char *Filename,
                                 OwningPtr<MemoryBuffer> &result,
                                 int64_t FileSize) {
  int OpenFlags = O_RDONLY;
#ifdef O_BINARY
  OpenFlags |= O_BINARY;  // Open input file in binary mode on win32.
#endif
  int FD = ::open(Filename, OpenFlags);
  if (FD == -1) {
    return error_code(errno, posix_category());
  }
  error_code ret = getOpenFile(FD, Filename, result, FileSize);
  close(FD);
  return ret;
}

static bool shouldUseMmap(int FD,
                          size_t FileSize,
                          size_t MapSize,
                          off_t Offset,
                          bool RequiresNullTerminator,
                          int PageSize) {
  // We don't use mmap for small files because this can severely fragment our
  // address space.
  if (MapSize < 4096*4)
    return false;

  if (!RequiresNullTerminator)
    return true;

  // If we don't know the file size, use fstat to find out.  fstat on an open
  // file descriptor is cheaper than stat on a random path.
  // FIXME: this chunk of code is duplicated, but it avoids a fstat when
  // RequiresNullTerminator = false and MapSize != -1.
  if (FileSize == size_t(-1)) {
    struct stat FileInfo;
    // TODO: This should use fstat64 when available.
    if (fstat(FD, &FileInfo) == -1) {
      return error_code(errno, posix_category());
    }
    FileSize = FileInfo.st_size;
  }

  // If we need a null terminator and the end of the map is inside the file,
  // we cannot use mmap.
  size_t End = Offset + MapSize;
  assert(End <= FileSize);
  if (End != FileSize)
    return false;

  // Don't try to map files that are exactly a multiple of the system page size
  // if we need a null terminator.
  if ((FileSize & (PageSize -1)) == 0)
    return false;

  return true;
}

error_code MemoryBuffer::getOpenFile(int FD, const char *Filename,
                                     OwningPtr<MemoryBuffer> &result,
                                     size_t FileSize, size_t MapSize,
                                     off_t Offset,
                                     bool RequiresNullTerminator) {
  static int PageSize = sys::Process::GetPageSize();

  // Default is to map the full file.
  if (MapSize == size_t(-1)) {
    // If we don't know the file size, use fstat to find out.  fstat on an open
    // file descriptor is cheaper than stat on a random path.
    if (FileSize == size_t(-1)) {
      struct stat FileInfo;
      // TODO: This should use fstat64 when available.
      if (fstat(FD, &FileInfo) == -1) {
        return error_code(errno, posix_category());
      }
      FileSize = FileInfo.st_size;
    }
    MapSize = FileSize;
  }

  if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
                    PageSize)) {
    off_t RealMapOffset = Offset & ~(PageSize - 1);
    off_t Delta = Offset - RealMapOffset;
    size_t RealMapSize = MapSize + Delta;

    if (const char *Pages = sys::Path::MapInFilePages(FD,
                                                      RealMapSize,
                                                      RealMapOffset)) {
      result.reset(GetNamedBuffer<MemoryBufferMMapFile>(
          StringRef(Pages + Delta, MapSize), Filename, RequiresNullTerminator));
      return success;
    }
  }

  MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
  if (!Buf) {
    // Failed to create a buffer. The only way it can fail is if
    // new(std::nothrow) returns 0.
    return make_error_code(errc::not_enough_memory);
  }

  OwningPtr<MemoryBuffer> SB(Buf);
  char *BufPtr = const_cast<char*>(SB->getBufferStart());

  size_t BytesLeft = MapSize;
  if (lseek(FD, Offset, SEEK_SET) == -1)
    return error_code(errno, posix_category());

  while (BytesLeft) {
    ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
    if (NumRead == -1) {
      if (errno == EINTR)
        continue;
      // Error while reading.
      return error_code(errno, posix_category());
    } else if (NumRead == 0) {
      // We hit EOF early, truncate and terminate buffer.
      Buf->BufferEnd = BufPtr;
      *BufPtr = 0;
      result.swap(SB);
      return success;
    }
    BytesLeft -= NumRead;
    BufPtr += NumRead;
  }

  result.swap(SB);
  return success;
}

//===----------------------------------------------------------------------===//
// MemoryBuffer::getSTDIN implementation.
//===----------------------------------------------------------------------===//

error_code MemoryBuffer::getSTDIN(OwningPtr<MemoryBuffer> &result) {
  // Read in all of the data from stdin, we cannot mmap stdin.
  //
  // FIXME: That isn't necessarily true, we should try to mmap stdin and
  // fallback if it fails.
  sys::Program::ChangeStdinToBinary();

  const ssize_t ChunkSize = 4096*4;
  SmallString<ChunkSize> Buffer;
  ssize_t ReadBytes;
  // Read into Buffer until we hit EOF.
  do {
    Buffer.reserve(Buffer.size() + ChunkSize);
    ReadBytes = read(0, Buffer.end(), ChunkSize);
    if (ReadBytes == -1) {
      if (errno == EINTR) continue;
      return error_code(errno, posix_category());
    }
    Buffer.set_size(Buffer.size() + ReadBytes);
  } while (ReadBytes != 0);

  result.reset(getMemBufferCopy(Buffer, "<stdin>"));
  return success;
}
<commit_msg>Check RequiresNullTerminator first, or we might read from an invalid address.<commit_after>//===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the MemoryBuffer interface.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/MemoryBuffer.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/system_error.h"
#include <cassert>
#include <cstdio>
#include <cstring>
#include <cerrno>
#include <new>
#include <sys/types.h>
#include <sys/stat.h>
#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
#include <sys/uio.h>
#else
#include <io.h>
#endif
#include <fcntl.h>
using namespace llvm;

namespace { const llvm::error_code success; }

//===----------------------------------------------------------------------===//
// MemoryBuffer implementation itself.
//===----------------------------------------------------------------------===//

MemoryBuffer::~MemoryBuffer() { }

/// init - Initialize this MemoryBuffer as a reference to externally allocated
/// memory, memory that we know is already null terminated.
void MemoryBuffer::init(const char *BufStart, const char *BufEnd,
                        bool RequiresNullTerminator) {
  assert((!RequiresNullTerminator || BufEnd[0] == 0) &&
         "Buffer is not null terminated!");
  BufferStart = BufStart;
  BufferEnd = BufEnd;
}

//===----------------------------------------------------------------------===//
// MemoryBufferMem implementation.
//===----------------------------------------------------------------------===//

/// CopyStringRef - Copies contents of a StringRef into a block of memory and
/// null-terminates it.
static void CopyStringRef(char *Memory, StringRef Data) {
  memcpy(Memory, Data.data(), Data.size());
  Memory[Data.size()] = 0; // Null terminate string.
}

/// GetNamedBuffer - Allocates a new MemoryBuffer with Name copied after it.
template <typename T>
static T* GetNamedBuffer(StringRef Buffer, StringRef Name,
                         bool RequiresNullTerminator) {
  char *Mem = static_cast<char*>(operator new(sizeof(T) + Name.size() + 1));
  CopyStringRef(Mem + sizeof(T), Name);
  return new (Mem) T(Buffer, RequiresNullTerminator);
}

namespace {
/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
class MemoryBufferMem : public MemoryBuffer {
public:
  MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
    init(InputData.begin(), InputData.end(), RequiresNullTerminator);
  }

  virtual const char *getBufferIdentifier() const {
     // The name is stored after the class itself.
    return reinterpret_cast<const char*>(this + 1);
  }
};
}

/// getMemBuffer - Open the specified memory range as a MemoryBuffer.  Note
/// that EndPtr[0] must be a null byte and be accessible!
MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData,
                                         StringRef BufferName,
                                         bool RequiresNullTerminator) {
  return GetNamedBuffer<MemoryBufferMem>(InputData, BufferName,
                                         RequiresNullTerminator);
}

/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
/// copying the contents and taking ownership of it.  This has no requirements
/// on EndPtr[0].
MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData,
                                             StringRef BufferName) {
  MemoryBuffer *Buf = getNewUninitMemBuffer(InputData.size(), BufferName);
  if (!Buf) return 0;
  memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(),
         InputData.size());
  return Buf;
}

/// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size
/// that is not initialized.  Note that the caller should initialize the
/// memory allocated by this method.  The memory is owned by the MemoryBuffer
/// object.
MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size,
                                                  StringRef BufferName) {
  // Allocate space for the MemoryBuffer, the data and the name. It is important
  // that MemoryBuffer and data are aligned so PointerIntPair works with them.
  size_t AlignedStringLen =
    RoundUpToAlignment(sizeof(MemoryBufferMem) + BufferName.size() + 1,
                       sizeof(void*)); // TODO: Is sizeof(void*) enough?
  size_t RealLen = AlignedStringLen + Size + 1;
  char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow));
  if (!Mem) return 0;

  // The name is stored after the class itself.
  CopyStringRef(Mem + sizeof(MemoryBufferMem), BufferName);

  // The buffer begins after the name and must be aligned.
  char *Buf = Mem + AlignedStringLen;
  Buf[Size] = 0; // Null terminate buffer.

  return new (Mem) MemoryBufferMem(StringRef(Buf, Size), true);
}

/// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that
/// is completely initialized to zeros.  Note that the caller should
/// initialize the memory allocated by this method.  The memory is owned by
/// the MemoryBuffer object.
MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) {
  MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName);
  if (!SB) return 0;
  memset(const_cast<char*>(SB->getBufferStart()), 0, Size);
  return SB;
}

/// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin
/// if the Filename is "-".  If an error occurs, this returns null and fills
/// in *ErrStr with a reason.  If stdin is empty, this API (unlike getSTDIN)
/// returns an empty buffer.
error_code MemoryBuffer::getFileOrSTDIN(StringRef Filename,
                                        OwningPtr<MemoryBuffer> &result,
                                        int64_t FileSize) {
  if (Filename == "-")
    return getSTDIN(result);
  return getFile(Filename, result, FileSize);
}

error_code MemoryBuffer::getFileOrSTDIN(const char *Filename,
                                        OwningPtr<MemoryBuffer> &result,
                                        int64_t FileSize) {
  if (strcmp(Filename, "-") == 0)
    return getSTDIN(result);
  return getFile(Filename, result, FileSize);
}

//===----------------------------------------------------------------------===//
// MemoryBuffer::getFile implementation.
//===----------------------------------------------------------------------===//

namespace {
/// MemoryBufferMMapFile - This represents a file that was mapped in with the
/// sys::Path::MapInFilePages method.  When destroyed, it calls the
/// sys::Path::UnMapFilePages method.
class MemoryBufferMMapFile : public MemoryBufferMem {
public:
  MemoryBufferMMapFile(StringRef Buffer, bool RequiresNullTerminator)
    : MemoryBufferMem(Buffer, RequiresNullTerminator) { }

  ~MemoryBufferMMapFile() {
    static int PageSize = sys::Process::GetPageSize();

    uintptr_t Start = reinterpret_cast<uintptr_t>(getBufferStart());
    size_t Size = getBufferSize();
    uintptr_t RealStart = Start & ~(PageSize - 1);
    size_t RealSize = Size + (Start - RealStart);

    sys::Path::UnMapFilePages(reinterpret_cast<const char*>(RealStart),
                              RealSize);
  }
};
}

error_code MemoryBuffer::getFile(StringRef Filename,
                                 OwningPtr<MemoryBuffer> &result,
                                 int64_t FileSize) {
  // Ensure the path is null terminated.
  SmallString<256> PathBuf(Filename.begin(), Filename.end());
  return MemoryBuffer::getFile(PathBuf.c_str(), result, FileSize);
}

error_code MemoryBuffer::getFile(const char *Filename,
                                 OwningPtr<MemoryBuffer> &result,
                                 int64_t FileSize) {
  int OpenFlags = O_RDONLY;
#ifdef O_BINARY
  OpenFlags |= O_BINARY;  // Open input file in binary mode on win32.
#endif
  int FD = ::open(Filename, OpenFlags);
  if (FD == -1) {
    return error_code(errno, posix_category());
  }
  error_code ret = getOpenFile(FD, Filename, result, FileSize);
  close(FD);
  return ret;
}

static bool shouldUseMmap(int FD,
                          size_t FileSize,
                          size_t MapSize,
                          off_t Offset,
                          bool RequiresNullTerminator,
                          int PageSize) {
  // We don't use mmap for small files because this can severely fragment our
  // address space.
  if (MapSize < 4096*4)
    return false;

  if (!RequiresNullTerminator)
    return true;

  // If we don't know the file size, use fstat to find out.  fstat on an open
  // file descriptor is cheaper than stat on a random path.
  // FIXME: this chunk of code is duplicated, but it avoids a fstat when
  // RequiresNullTerminator = false and MapSize != -1.
  if (FileSize == size_t(-1)) {
    struct stat FileInfo;
    // TODO: This should use fstat64 when available.
    if (fstat(FD, &FileInfo) == -1) {
      return error_code(errno, posix_category());
    }
    FileSize = FileInfo.st_size;
  }

  // If we need a null terminator and the end of the map is inside the file,
  // we cannot use mmap.
  size_t End = Offset + MapSize;
  assert(End <= FileSize);
  if (End != FileSize)
    return false;

  // Don't try to map files that are exactly a multiple of the system page size
  // if we need a null terminator.
  if ((FileSize & (PageSize -1)) == 0)
    return false;

  return true;
}

error_code MemoryBuffer::getOpenFile(int FD, const char *Filename,
                                     OwningPtr<MemoryBuffer> &result,
                                     size_t FileSize, size_t MapSize,
                                     off_t Offset,
                                     bool RequiresNullTerminator) {
  static int PageSize = sys::Process::GetPageSize();

  // Default is to map the full file.
  if (MapSize == size_t(-1)) {
    // If we don't know the file size, use fstat to find out.  fstat on an open
    // file descriptor is cheaper than stat on a random path.
    if (FileSize == size_t(-1)) {
      struct stat FileInfo;
      // TODO: This should use fstat64 when available.
      if (fstat(FD, &FileInfo) == -1) {
        return error_code(errno, posix_category());
      }
      FileSize = FileInfo.st_size;
    }
    MapSize = FileSize;
  }

  if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
                    PageSize)) {
    off_t RealMapOffset = Offset & ~(PageSize - 1);
    off_t Delta = Offset - RealMapOffset;
    size_t RealMapSize = MapSize + Delta;

    if (const char *Pages = sys::Path::MapInFilePages(FD,
                                                      RealMapSize,
                                                      RealMapOffset)) {
      result.reset(GetNamedBuffer<MemoryBufferMMapFile>(
          StringRef(Pages + Delta, MapSize), Filename, RequiresNullTerminator));
      return success;
    }
  }

  MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
  if (!Buf) {
    // Failed to create a buffer. The only way it can fail is if
    // new(std::nothrow) returns 0.
    return make_error_code(errc::not_enough_memory);
  }

  OwningPtr<MemoryBuffer> SB(Buf);
  char *BufPtr = const_cast<char*>(SB->getBufferStart());

  size_t BytesLeft = MapSize;
  if (lseek(FD, Offset, SEEK_SET) == -1)
    return error_code(errno, posix_category());

  while (BytesLeft) {
    ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
    if (NumRead == -1) {
      if (errno == EINTR)
        continue;
      // Error while reading.
      return error_code(errno, posix_category());
    } else if (NumRead == 0) {
      // We hit EOF early, truncate and terminate buffer.
      Buf->BufferEnd = BufPtr;
      *BufPtr = 0;
      result.swap(SB);
      return success;
    }
    BytesLeft -= NumRead;
    BufPtr += NumRead;
  }

  result.swap(SB);
  return success;
}

//===----------------------------------------------------------------------===//
// MemoryBuffer::getSTDIN implementation.
//===----------------------------------------------------------------------===//

error_code MemoryBuffer::getSTDIN(OwningPtr<MemoryBuffer> &result) {
  // Read in all of the data from stdin, we cannot mmap stdin.
  //
  // FIXME: That isn't necessarily true, we should try to mmap stdin and
  // fallback if it fails.
  sys::Program::ChangeStdinToBinary();

  const ssize_t ChunkSize = 4096*4;
  SmallString<ChunkSize> Buffer;
  ssize_t ReadBytes;
  // Read into Buffer until we hit EOF.
  do {
    Buffer.reserve(Buffer.size() + ChunkSize);
    ReadBytes = read(0, Buffer.end(), ChunkSize);
    if (ReadBytes == -1) {
      if (errno == EINTR) continue;
      return error_code(errno, posix_category());
    }
    Buffer.set_size(Buffer.size() + ReadBytes);
  } while (ReadBytes != 0);

  result.reset(getMemBufferCopy(Buffer, "<stdin>"));
  return success;
}
<|endoftext|>


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

#include "config.h"

#if HAVE_DUNE_FEM && HAVE_ALUGRID

# ifndef DUNE_GDT_LOCALEVALUATION_SWIPDG_DISABLE_WARNINGS
#   define DUNE_GDT_LOCALEVALUATION_SWIPDG_DISABLE_WARNINGS
# endif
# ifndef DUNE_HDD_LINEARELLIPTIC_TESTCASES_BASE_DISABLE_WARNING
#   define DUNE_HDD_LINEARELLIPTIC_TESTCASES_BASE_DISABLE_WARNING
# endif

# include <dune/fem/misc/mpimanager.hh>

# include <dune/stuff/common/ranges.hh>
# include <dune/stuff/common/timedlogging.hh>
# include <dune/stuff/grid/search.hh>

# include <dune/gdt/operators/prolongations.hh>
# include <dune/gdt/playground/operators/fluxreconstruction.hh>
# include <dune/gdt/playground/spaces/finitevolume/default.hh>
# include <dune/gdt/playground/spaces/raviartthomas/pdelab.hh>
# include <dune/gdt/products/elliptic.hh>

# include <dune/hdd/linearelliptic/testcases/OS2015.hh>
# include <dune/hdd/linearelliptic/discretizations/block-swipdg.hh>
# include <dune/hdd/linearelliptic/estimators/block-swipdg.hh>

using namespace Dune;
using namespace Dune::Stuff;
using namespace Dune::Pymor;
using namespace Dune::GDT;
using namespace Dune::HDD;

static const Parameter mu_min("mu", 0.1);
static const Parameter mu_max("mu", 1.0);
static const Parameter mu_bar("mu", 0.1);
static const Parameter mu_hat("mu", 0.1);

static const size_t over_integrate = 2;

template< class SpaceType, class VectorType, class ProblemType >
Stuff::LA::CommonDenseVector< double > compute_indicator_distribution(const SpaceType& space,
                                                                      const VectorType& vector,
                                                                      const ProblemType& problem,
                                                                      const Parameter& mu)
{
  typedef LinearElliptic::Estimators::BlockSWIPDG< SpaceType,
                                                   VectorType,
                                                   ProblemType,
                                                   typename SpaceType::GridViewType::Grid > Estimator;
  auto eta_Ts = Estimator::estimate_local(space,
                                          vector,
                                          problem,
                                          "eta_OS2014_*",
                                          {{"mu",     mu},
                                           {"mu_bar", mu_bar},
                                           {"mu_hat", mu_hat},
                                           {"parameter_range_min", mu_min},
                                           {"parameter_range_max", mu_max}});
  double eta = 0.0;
  for (const auto& eta_T : eta_Ts)
    eta += std::pow(eta_T, 2);
  eta = std::sqrt(eta);
  for (auto& eta_T : eta_Ts)
    eta_T /= eta;
  return eta_Ts;
} // ... compute_indicator_distribution(...)

template< class DiscretizationType, class DifferenceType, class DiffusionFactorType, class DiffusionTensorType >
Stuff::LA::CommonDenseVector< double > compute_error_distribution(const DiscretizationType& discretization,
                                                                  const DiscretizationType& reference_discretization,
                                                                  const DifferenceType& difference,
                                                                  const DiffusionFactorType& diffusion_factor,
                                                                  const DiffusionTensorType& diffusion_tensor)
{
  auto error_product = Products::make_elliptic_localizable(reference_discretization.grid_view(),
                                                           difference,
                                                           diffusion_factor,
                                                           diffusion_tensor,
                                                           over_integrate);
  error_product.prepare();
  auto error_distribution = discretization.create_vector();
  auto entity_search = Stuff::Grid::make_entity_in_level_search(discretization.grid_view());
  for (const auto& entity : DSC::entityRange(reference_discretization.grid_view())) {
    // search for the father entity in the (coarser) grid view
    const auto points = {entity.geometry().center()};
    const auto father_entity_ptr_ptrs = entity_search(points);
    if (father_entity_ptr_ptrs.size() != 1)
      DUNE_THROW(Stuff::Exceptions::internal_error, father_entity_ptr_ptrs.size());
    const auto& father_entity_ptr_ptr = father_entity_ptr_ptrs[0];
    assert(father_entity_ptr_ptr);
    const auto father_entity_ptr = *father_entity_ptr_ptr;
    const auto& father_entity = *father_entity_ptr;
    assert(discretization.grid_view().contains(father_entity));
    // compute local error
    error_distribution.add_to_entry(discretization.grid_view().indexSet().index(father_entity),
                                    error_product.compute_locally(entity));
  }
  // sum local errors on the subdomain level
  const auto ms_grid = discretization.ansatz_space()->ms_grid();
  auto error_distribution_on_subdomains = Stuff::LA::CommonDenseVector< double >(ms_grid->size(), 0.0);
  error_distribution_on_subdomains *= 0.0;
  for (size_t ss = 0; ss < ms_grid->size(); ++ss)
    for (const auto& entity : DSC::entityRange(ms_grid->localGridPart(ss)))
      error_distribution_on_subdomains[ss]
          += error_distribution[discretization.grid_view().indexSet().index(entity)];
  double error = 0.0;
  for (const auto& element : error_distribution_on_subdomains)
    error += element;
  error = std::sqrt(error);
  for (auto& element : error_distribution_on_subdomains)
    element = std::sqrt(element) / error;
  return error_distribution_on_subdomains;
} // ... compute_error_distribution(...)

int main(int argc, char** argv)
{
  try {
    Dune::Fem::MPIManager::initialize(argc, argv);

    DSC::TimedLogger().create(0, 0);
    auto logger = DSC::TimedLogger().get("main");
    logger.info() << "creating grid and test case ..." << std::endl;

    typedef ALUGrid< 2, 2, simplex, conforming > GridType;
    typedef LinearElliptic::TestCases::OS2015::Multiscale< GridType > TestCaseType;
    const TestCaseType test_case({{"mu",     mu_max},
                                  {"mu_bar", mu_bar},
                                  {"mu_hat", mu_hat},
                                  {"parameter_range_min", mu_min},
                                  {"parameter_range_max", mu_max}},
                                 "[25 5 1 ]");
    const auto& problem = test_case.problem();
    auto problem_mu_min = problem.with_mu(mu_min);
    auto problem_mu_max = problem.with_mu(mu_max);
    auto problem_mu_bar = problem.with_mu(mu_bar);

    logger.info() << "discretizing ..." << std::endl;
    auto disc = LinearElliptic::Discretizations::make_block_swipdg< Stuff::LA::ChooseBackend::eigen_sparse >(
                  *test_case.level_provider(0),
                  test_case.boundary_info(),
                  problem);
    disc.init();

    logger.info() << "visualizing problems ..." << std::endl;
    problem.visualize(disc.grid_view(), "parametric_problem");
    problem_mu_min->visualize(disc.grid_view(), "problem_mu_min");
    problem_mu_max->visualize(disc.grid_view(), "problem_mu_max");

    logger.info() << "solving for " << mu_min << " ..." << std::endl;
    typedef typename decltype(disc)::VectorType VectorType;
    auto pressure_mu_min = make_discrete_function< VectorType >(*disc.ansatz_space(), "pressure");
    disc.solve(pressure_mu_min.vector(), mu_min);
    logger.info() << "solving for " << mu_max << " ..." << std::endl;
    auto pressure_mu_max = make_discrete_function< VectorType >(*disc.ansatz_space(), "pressure");
    disc.solve(pressure_mu_max.vector(), mu_max);

    logger.info() << "visualizing solutions ..." << std::endl;
    pressure_mu_min.visualize("pressure_mu_min");
    pressure_mu_max.visualize("pressure_mu_max");

    logger.info() << "reconstructing diffusive fluxes ..." << std::endl;
    Spaces::RaviartThomas::PdelabBased< typename std::remove_reference< decltype(disc) >::type::GridViewType,
                                        0, double, 2 > rt_space(disc.grid_view());
    auto reconstruction_mu_min = GDT::Operators::make_diffusive_flux_reconstruction(disc.grid_view(),
                                                                                *problem_mu_min->diffusion_factor()->affine_part(),
                                                                                *problem_mu_min->diffusion_tensor()->affine_part(),
                                                                                over_integrate);
    auto reconstruction_mu_max = GDT::Operators::make_diffusive_flux_reconstruction(disc.grid_view(),
                                                                                *problem_mu_max->diffusion_factor()->affine_part(),
                                                                                *problem_mu_max->diffusion_tensor()->affine_part(),
                                                                                over_integrate);
    auto velocity_mu_min = make_discrete_function< VectorType >(rt_space, "velocity");
    auto velocity_mu_max = make_discrete_function< VectorType >(rt_space, "velocity");
    reconstruction_mu_min.apply(pressure_mu_min, velocity_mu_min);
    reconstruction_mu_max.apply(pressure_mu_max, velocity_mu_max);

    logger.info() << "visualizing diffusive fluxes ..." << std::endl;
    velocity_mu_min.visualize("velocity_mu_min");
    velocity_mu_max.visualize("velocity_mu_max");

    logger.info() << "computing local estimator contributions ..." << std::endl;
    const auto eta_Ts_mu_min = compute_indicator_distribution(*disc.ansatz_space(),
                                                                    pressure_mu_min.vector(),
                                                                    problem,
                                                                    mu_min);
    const auto eta_Ts_mu_max = compute_indicator_distribution(*disc.ansatz_space(),
                                                                    pressure_mu_max.vector(),
                                                                    problem,
                                                                    mu_max);

    logger.info() << "computing reference solutions ..." << std::endl;
    auto reference_disc = LinearElliptic::Discretizations::make_block_swipdg< Stuff::LA::ChooseBackend::eigen_sparse >(
                  *test_case.reference_provider(),
                  test_case.boundary_info(),
                  problem);
    reference_disc.init();
    auto reference_pressure_mu_min = make_discrete_function< VectorType >(*reference_disc.ansatz_space());
    auto reference_pressure_mu_max = make_discrete_function< VectorType >(*reference_disc.ansatz_space());
    reference_disc.solve(reference_pressure_mu_min.vector(), mu_min);
    reference_disc.solve(reference_pressure_mu_max.vector(), mu_max);

    logger.info() << "prolonging solutions to reference grid ..." << std::endl;
    auto pressure_mu_min_on_reference = make_discrete_function< VectorType >(*reference_disc.ansatz_space());
    auto pressure_mu_max_on_reference = make_discrete_function< VectorType >(*reference_disc.ansatz_space());
    GDT::Operators::prolong(pressure_mu_min, pressure_mu_min_on_reference);
    GDT::Operators::prolong(pressure_mu_max, pressure_mu_max_on_reference);

    logger.info() << "computing local error contributions ..." << std::endl;
    auto error_distribution_mu_min_on_subdomains
        = compute_error_distribution(disc,
                                     reference_disc,
                                     reference_pressure_mu_min - pressure_mu_min_on_reference,
                                     *problem_mu_bar->diffusion_factor()->affine_part(),
                                     *problem_mu_bar->diffusion_tensor()->affine_part());
    auto error_distribution_mu_max_on_subdomains
        = compute_error_distribution(disc,
                                     reference_disc,
                                     reference_pressure_mu_max - pressure_mu_max_on_reference,
                                     *problem_mu_bar->diffusion_factor()->affine_part(),
                                     *problem_mu_bar->diffusion_tensor()->affine_part());

    logger.info() << "visualizing local errors and indicators ..." << std::endl;
    Spaces::FiniteVolume::Default< typename std::remove_reference< decltype(disc) >::type::GridViewType,
                                   double, 1 > fv_space(disc.grid_view());
    auto indicator_visualization_mu_min = make_discrete_function< VectorType >(fv_space, "distribution");
    auto indicator_visualization_mu_max = make_discrete_function< VectorType >(fv_space, "distribution");
    auto error_visualization_mu_min = make_discrete_function< VectorType >(fv_space, "distribution");
    auto error_visualization_mu_max = make_discrete_function< VectorType >(fv_space, "distribution");
    const auto ms_grid = disc.ansatz_space()->ms_grid();
    for (size_t ss = 0; ss < ms_grid->size(); ++ss)
      for (const auto& entity : DSC::entityRange(ms_grid->localGridPart(ss))) {
        const auto index = disc.grid_view().indexSet().index(entity);
        indicator_visualization_mu_min.vector().set_entry(index, eta_Ts_mu_min[ss]);
        indicator_visualization_mu_max.vector().set_entry(index, eta_Ts_mu_max[ss]);
        error_visualization_mu_min.vector().set_entry(disc.grid_view().indexSet().index(entity),
                                                      error_distribution_mu_min_on_subdomains[ss]);
        error_visualization_mu_max.vector().set_entry(disc.grid_view().indexSet().index(entity),
                                                      error_distribution_mu_max_on_subdomains[ss]);
      }
    indicator_visualization_mu_min.visualize("indicator_distribution_mu_min");
    indicator_visualization_mu_max.visualize("indicator_distribution_mu_max");
    error_visualization_mu_min.visualize("error_distribution_mu_min");
    error_visualization_mu_max.visualize("error_distribution_mu_max");

    logger.info() << "finished" << std::endl;

  } catch (Dune::Exception& ee) {
    std::cout << "Dune reported error: " << ee.what() << std::endl;
  } catch (std::exception& ee) {
    std::cout << "stl reported error:\n" << ee.what() << std::endl;
  }

  return 0;
} // ... main(...)

#elif HAVE_DUNE_FEM // HAVE_DUNE_FEM && HAVE_ALUGRID

int main(int /*argc*/, char** /*argv*/)
{
  std::cerr << "Error: you are missing ALUGrid!" << std::endl;
}

#elif HAVE_ALUGRID // HAVE_DUNE_FEM && HAVE_ALUGRID

int main(int /*argc*/, char** /*argv*/)
{
  std::cerr << "Error: you are missing dune-fem!" << std::endl;
}

#else // HAVE_DUNE_FEM && HAVE_ALUGRID

int main(int /*argc*/, char** /*argv*/)
{
  std::cerr << "Error: you are missing dune-fem and ALUGrid!" << std::endl;
}

#endif // HAVE_DUNE_FEM && HAVE_ALUGRID
<commit_msg>[examples...OS2015_SISC__6_1_multiscale_example] bring up to date<commit_after>// This file is part of the dune-hdd project:
//   http://users.dune-project.org/projects/dune-hdd
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include "config.h"

#if HAVE_DUNE_FEM && HAVE_ALUGRID

# ifndef DUNE_GDT_LOCALEVALUATION_SWIPDG_DISABLE_WARNINGS
#   define DUNE_GDT_LOCALEVALUATION_SWIPDG_DISABLE_WARNINGS
# endif
# ifndef DUNE_HDD_LINEARELLIPTIC_TESTCASES_BASE_DISABLE_WARNING
#   define DUNE_HDD_LINEARELLIPTIC_TESTCASES_BASE_DISABLE_WARNING
# endif

# include <dune/fem/misc/mpimanager.hh>

# include <dune/stuff/common/ranges.hh>
# include <dune/stuff/common/timedlogging.hh>
# include <dune/stuff/grid/search.hh>

# include <dune/gdt/operators/prolongations.hh>
# include <dune/gdt/playground/operators/fluxreconstruction.hh>
# include <dune/gdt/spaces/fv/default.hh>
# include <dune/gdt/spaces/rt/pdelab.hh>
# include <dune/gdt/products/elliptic.hh>

# include <dune/hdd/linearelliptic/testcases/OS2015.hh>
# include <dune/hdd/linearelliptic/discretizations/block-swipdg.hh>
# include <dune/hdd/linearelliptic/estimators/block-swipdg.hh>

using namespace Dune;
using namespace Dune::Stuff;
using namespace Dune::Pymor;
using namespace Dune::GDT;
using namespace Dune::HDD;

static const Parameter mu_min("mu", 0.1);
static const Parameter mu_max("mu", 1.0);
static const Parameter mu_bar("mu", 0.1);
static const Parameter mu_hat("mu", 0.1);

static const size_t over_integrate = 2;

template< class SpaceType, class VectorType, class ProblemType >
Stuff::LA::CommonDenseVector< double > compute_indicator_distribution(const SpaceType& space,
                                                                      const VectorType& vector,
                                                                      const ProblemType& problem,
                                                                      const Parameter& mu)
{
  typedef LinearElliptic::Estimators::BlockSWIPDG< SpaceType,
                                                   VectorType,
                                                   ProblemType,
                                                   typename SpaceType::GridViewType::Grid > Estimator;
  auto eta_Ts = Estimator::estimate_local(space,
                                          vector,
                                          problem,
                                          "eta_OS2014_*",
                                          {{"mu",     mu},
                                           {"mu_bar", mu_bar},
                                           {"mu_hat", mu_hat},
                                           {"parameter_range_min", mu_min},
                                           {"parameter_range_max", mu_max}});
  double eta = 0.0;
  for (const auto& eta_T : eta_Ts)
    eta += std::pow(eta_T, 2);
  eta = std::sqrt(eta);
  for (auto& eta_T : eta_Ts)
    eta_T /= eta;
  return eta_Ts;
} // ... compute_indicator_distribution(...)

template< class DiscretizationType, class DifferenceType, class DiffusionFactorType, class DiffusionTensorType >
Stuff::LA::CommonDenseVector< double > compute_error_distribution(const DiscretizationType& discretization,
                                                                  const DiscretizationType& reference_discretization,
                                                                  const DifferenceType& difference,
                                                                  const DiffusionFactorType& diffusion_factor,
                                                                  const DiffusionTensorType& diffusion_tensor)
{
  auto error_product = Products::make_elliptic_localizable(reference_discretization.grid_view(),
                                                           difference,
                                                           diffusion_factor,
                                                           diffusion_tensor,
                                                           over_integrate);
  error_product.prepare();
  auto error_distribution = discretization.create_vector();
  auto entity_search = Stuff::Grid::make_entity_in_level_search(discretization.grid_view());
  for (const auto& entity : DSC::entityRange(reference_discretization.grid_view())) {
    // search for the father entity in the (coarser) grid view
    const auto points = {entity.geometry().center()};
    const auto father_entity_ptr_ptrs = entity_search(points);
    if (father_entity_ptr_ptrs.size() != 1)
      DUNE_THROW(Stuff::Exceptions::internal_error, father_entity_ptr_ptrs.size());
    const auto& father_entity_ptr_ptr = father_entity_ptr_ptrs[0];
    assert(father_entity_ptr_ptr);
    const auto father_entity_ptr = *father_entity_ptr_ptr;
    const auto& father_entity = *father_entity_ptr;
    assert(discretization.grid_view().contains(father_entity));
    // compute local error
    error_distribution.add_to_entry(discretization.grid_view().indexSet().index(father_entity),
                                    error_product.compute_locally(entity));
  }
  // sum local errors on the subdomain level
  const auto ms_grid = discretization.ansatz_space().ms_grid();
  auto error_distribution_on_subdomains = Stuff::LA::CommonDenseVector< double >(ms_grid->size(), 0.0);
  error_distribution_on_subdomains *= 0.0;
  for (size_t ss = 0; ss < ms_grid->size(); ++ss)
    for (const auto& entity : DSC::entityRange(ms_grid->localGridPart(ss)))
      error_distribution_on_subdomains[ss]
          += error_distribution[discretization.grid_view().indexSet().index(entity)];
  double error = 0.0;
  for (const auto& element : error_distribution_on_subdomains)
    error += element;
  error = std::sqrt(error);
  for (auto& element : error_distribution_on_subdomains)
    element = std::sqrt(element) / error;
  return error_distribution_on_subdomains;
} // ... compute_error_distribution(...)

int main(int argc, char** argv)
{
  try {
    Dune::Fem::MPIManager::initialize(argc, argv);

    DSC::TimedLogger().create(0, 0);
    auto logger = DSC::TimedLogger().get("main");
    logger.info() << "creating grid and test case ..." << std::endl;

    typedef ALUGrid< 2, 2, simplex, conforming > GridType;
    typedef LinearElliptic::TestCases::OS2015::Multiscale< GridType > TestCaseType;
    const TestCaseType test_case({{"mu",     mu_max},
                                  {"mu_bar", mu_bar},
                                  {"mu_hat", mu_hat},
                                  {"parameter_range_min", mu_min},
                                  {"parameter_range_max", mu_max}},
                                 "[25 5 1 ]");
    const auto& problem = test_case.problem();
    auto problem_mu_min = problem.with_mu(mu_min);
    auto problem_mu_max = problem.with_mu(mu_max);
    auto problem_mu_bar = problem.with_mu(mu_bar);

    logger.info() << "discretizing ..." << std::endl;
    auto disc = LinearElliptic::Discretizations::make_block_swipdg< Stuff::LA::ChooseBackend::eigen_sparse >(
                  *test_case.level_provider(0),
                  test_case.boundary_info(),
                  problem);
    disc.init();

    logger.info() << "visualizing problems ..." << std::endl;
    problem.visualize(disc.grid_view(), "parametric_problem");
    problem_mu_min->visualize(disc.grid_view(), "problem_mu_min");
    problem_mu_max->visualize(disc.grid_view(), "problem_mu_max");

    logger.info() << "solving for " << mu_min << " ..." << std::endl;
    typedef typename decltype(disc)::VectorType VectorType;
    auto pressure_mu_min = make_discrete_function< VectorType >(disc.ansatz_space(), "pressure");
    disc.solve(pressure_mu_min.vector(), mu_min);
    logger.info() << "solving for " << mu_max << " ..." << std::endl;
    auto pressure_mu_max = make_discrete_function< VectorType >(disc.ansatz_space(), "pressure");
    disc.solve(pressure_mu_max.vector(), mu_max);

    logger.info() << "visualizing solutions ..." << std::endl;
    pressure_mu_min.visualize("pressure_mu_min");
    pressure_mu_max.visualize("pressure_mu_max");

    logger.info() << "reconstructing diffusive fluxes ..." << std::endl;
    Spaces::RT::PdelabBased< typename std::remove_reference< decltype(disc) >::type::GridViewType, 0, double, 2 >
        rt_space(disc.grid_view());
    auto reconstruction_mu_min = GDT::Operators::make_diffusive_flux_reconstruction(disc.grid_view(),
                                                                                *problem_mu_min->diffusion_factor()->affine_part(),
                                                                                *problem_mu_min->diffusion_tensor()->affine_part(),
                                                                                over_integrate);
    auto reconstruction_mu_max = GDT::Operators::make_diffusive_flux_reconstruction(disc.grid_view(),
                                                                                *problem_mu_max->diffusion_factor()->affine_part(),
                                                                                *problem_mu_max->diffusion_tensor()->affine_part(),
                                                                                over_integrate);
    auto velocity_mu_min = make_discrete_function< VectorType >(rt_space, "velocity");
    auto velocity_mu_max = make_discrete_function< VectorType >(rt_space, "velocity");
    reconstruction_mu_min.apply(pressure_mu_min, velocity_mu_min);
    reconstruction_mu_max.apply(pressure_mu_max, velocity_mu_max);

    logger.info() << "visualizing diffusive fluxes ..." << std::endl;
    velocity_mu_min.visualize("velocity_mu_min");
    velocity_mu_max.visualize("velocity_mu_max");

    logger.info() << "computing local estimator contributions ..." << std::endl;
    const auto eta_Ts_mu_min = compute_indicator_distribution(disc.ansatz_space(),
                                                              pressure_mu_min.vector(),
                                                              problem,
                                                              mu_min);
    const auto eta_Ts_mu_max = compute_indicator_distribution(disc.ansatz_space(),
                                                              pressure_mu_max.vector(),
                                                              problem,
                                                              mu_max);

    logger.info() << "computing reference solutions ..." << std::endl;
    auto reference_disc = LinearElliptic::Discretizations::make_block_swipdg< Stuff::LA::ChooseBackend::eigen_sparse >(
                  *test_case.reference_provider(),
                  test_case.boundary_info(),
                  problem);
    reference_disc.init();
    auto reference_pressure_mu_min = make_discrete_function< VectorType >(reference_disc.ansatz_space());
    auto reference_pressure_mu_max = make_discrete_function< VectorType >(reference_disc.ansatz_space());
    reference_disc.solve(reference_pressure_mu_min.vector(), mu_min);
    reference_disc.solve(reference_pressure_mu_max.vector(), mu_max);

    logger.info() << "prolonging solutions to reference grid ..." << std::endl;
    auto pressure_mu_min_on_reference = make_discrete_function< VectorType >(reference_disc.ansatz_space());
    auto pressure_mu_max_on_reference = make_discrete_function< VectorType >(reference_disc.ansatz_space());
    GDT::Operators::prolong(pressure_mu_min, pressure_mu_min_on_reference);
    GDT::Operators::prolong(pressure_mu_max, pressure_mu_max_on_reference);

    logger.info() << "computing local error contributions ..." << std::endl;
    auto error_distribution_mu_min_on_subdomains
        = compute_error_distribution(disc,
                                     reference_disc,
                                     reference_pressure_mu_min - pressure_mu_min_on_reference,
                                     *problem_mu_bar->diffusion_factor()->affine_part(),
                                     *problem_mu_bar->diffusion_tensor()->affine_part());
    auto error_distribution_mu_max_on_subdomains
        = compute_error_distribution(disc,
                                     reference_disc,
                                     reference_pressure_mu_max - pressure_mu_max_on_reference,
                                     *problem_mu_bar->diffusion_factor()->affine_part(),
                                     *problem_mu_bar->diffusion_tensor()->affine_part());

    logger.info() << "visualizing local errors and indicators ..." << std::endl;
    Spaces::FV::Default< typename std::remove_reference< decltype(disc) >::type::GridViewType, double, 1 >
        fv_space(disc.grid_view());
    auto indicator_visualization_mu_min = make_discrete_function< VectorType >(fv_space, "distribution");
    auto indicator_visualization_mu_max = make_discrete_function< VectorType >(fv_space, "distribution");
    auto error_visualization_mu_min = make_discrete_function< VectorType >(fv_space, "distribution");
    auto error_visualization_mu_max = make_discrete_function< VectorType >(fv_space, "distribution");
    const auto ms_grid = disc.ansatz_space().ms_grid();
    for (size_t ss = 0; ss < ms_grid->size(); ++ss)
      for (const auto& entity : DSC::entityRange(ms_grid->localGridPart(ss))) {
        const auto index = disc.grid_view().indexSet().index(entity);
        indicator_visualization_mu_min.vector().set_entry(index, eta_Ts_mu_min[ss]);
        indicator_visualization_mu_max.vector().set_entry(index, eta_Ts_mu_max[ss]);
        error_visualization_mu_min.vector().set_entry(disc.grid_view().indexSet().index(entity),
                                                      error_distribution_mu_min_on_subdomains[ss]);
        error_visualization_mu_max.vector().set_entry(disc.grid_view().indexSet().index(entity),
                                                      error_distribution_mu_max_on_subdomains[ss]);
      }
    indicator_visualization_mu_min.visualize("indicator_distribution_mu_min");
    indicator_visualization_mu_max.visualize("indicator_distribution_mu_max");
    error_visualization_mu_min.visualize("error_distribution_mu_min");
    error_visualization_mu_max.visualize("error_distribution_mu_max");

    logger.info() << "finished" << std::endl;

  } catch (Dune::Exception& ee) {
    std::cout << "Dune reported error: " << ee.what() << std::endl;
  } catch (std::exception& ee) {
    std::cout << "stl reported error:\n" << ee.what() << std::endl;
  }

  return 0;
} // ... main(...)

#elif HAVE_DUNE_FEM // HAVE_DUNE_FEM && HAVE_ALUGRID

int main(int /*argc*/, char** /*argv*/)
{
  std::cerr << "Error: you are missing ALUGrid!" << std::endl;
}

#elif HAVE_ALUGRID // HAVE_DUNE_FEM && HAVE_ALUGRID

int main(int /*argc*/, char** /*argv*/)
{
  std::cerr << "Error: you are missing dune-fem!" << std::endl;
}

#else // HAVE_DUNE_FEM && HAVE_ALUGRID

int main(int /*argc*/, char** /*argv*/)
{
  std::cerr << "Error: you are missing dune-fem and ALUGrid!" << std::endl;
}

#endif // HAVE_DUNE_FEM && HAVE_ALUGRID
<|endoftext|>


<commit_before>//===- Darwin/Memory.cpp - Darwin Memory Implementation ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides the Darwin specific implementation of various Memory
// management utilities
//
//===----------------------------------------------------------------------===//

// Include the generic unix implementation
#include "../Unix/Memory.cpp"
#include "llvm/System/Process.h"
#include <sys/mman.h>

namespace llvm {
using namespace sys;

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only Darwin specific code
//===          and must not be generic UNIX code (see ../Unix/Memory.cpp)
//===----------------------------------------------------------------------===//

/// AllocateRWXMemory - Allocate a slab of memory with read/write/execute
/// permissions.  This is typically used for JIT applications where we want
/// to emit code to the memory then jump to it.  Getting this type of memory
/// is very OS specific.
///
MemoryBlock Memory::AllocateRWX(unsigned NumBytes) {
  if (NumBytes == 0) return MemoryBlock();

  static const long pageSize = Process::GetPageSize();
  unsigned NumPages = (NumBytes+pageSize-1)/pageSize;

  void *pa = mmap(0, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
                  MAP_PRIVATE|MAP_ANON, -1, 0);
  if (pa == MAP_FAILED) {
    char msg[MAXPATHLEN];
    strerror_r(errno, msg, MAXPATHLEN-1);
    throw std::string("Can't allocate RWX Memory: ") + msg;
  }
  MemoryBlock result;
  result.Address = pa;
  result.Size = NumPages*pageSize;
  return result;
}

void Memory::ReleaseRWX(MemoryBlock& M) {
  if (M.Address == 0 || M.Size == 0) return;
  if (0 != munmap(M.Address, M.Size)) {
    char msg[MAXPATHLEN];
    strerror_r(errno, msg, MAXPATHLEN-1);
    throw std::string("Can't release RWX Memory: ") + msg;
  }
}

}

// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab
<commit_msg>Fix some grammar<commit_after>//===- Darwin/Memory.cpp - Darwin Memory Implementation ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides the Darwin specific implementation of various Memory
// management utilities
//
//===----------------------------------------------------------------------===//

// Include the generic unix implementation
#include "../Unix/Memory.cpp"
#include "llvm/System/Process.h"
#include <sys/mman.h>

namespace llvm {
using namespace sys;

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only Darwin-specific code
//===          and must not be generic UNIX code (see ../Unix/Memory.cpp)
//===----------------------------------------------------------------------===//

/// AllocateRWXMemory - Allocate a slab of memory with read/write/execute
/// permissions.  This is typically used for JIT applications where we want
/// to emit code to the memory and then jump to it.  Getting this type of memory
/// is very OS-specific.
///
MemoryBlock Memory::AllocateRWX(unsigned NumBytes) {
  if (NumBytes == 0) return MemoryBlock();

  static const long pageSize = Process::GetPageSize();
  unsigned NumPages = (NumBytes+pageSize-1)/pageSize;

  void *pa = mmap(0, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
                  MAP_PRIVATE|MAP_ANON, -1, 0);
  if (pa == MAP_FAILED) {
    char msg[MAXPATHLEN];
    strerror_r(errno, msg, MAXPATHLEN-1);
    throw std::string("Can't allocate RWX Memory: ") + msg;
  }
  MemoryBlock result;
  result.Address = pa;
  result.Size = NumPages*pageSize;
  return result;
}

void Memory::ReleaseRWX(MemoryBlock& M) {
  if (M.Address == 0 || M.Size == 0) return;
  if (0 != munmap(M.Address, M.Size)) {
    char msg[MAXPATHLEN];
    strerror_r(errno, msg, MAXPATHLEN-1);
    throw std::string("Can't release RWX Memory: ") + msg;
  }
}

}

// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab
<|endoftext|>


<commit_before>#include <iostream>

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

void print(const boost::system::error_code &e, boost::asio::deadline_timer& t, int& count)
{
	std::cout << "A timer thing No. " << count++ << std::endl;
}

int main(int argc, char *argv[])
{
	boost::asio::io_service io;

	boost::asio::deadline_timer t1(io, boost::posix_time::seconds(1));
	boost::asio::deadline_timer t2(io, boost::posix_time::seconds(2));
	t1.async_wait(&print);
	std::cout << "Between" << std::endl;
	t2.async_wait(&print);

	io.run();

	std::cout << "Meantime stuff" << std::endl;

	return 0;
}
<commit_msg>chat: finish the third asio example<commit_after>#include <iostream>

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

void print(const boost::system::error_code &e, boost::asio::deadline_timer *t, int *count)
{
	if (*count < 5) {
		std::cout << "A timer thing No. " << (*count)++ << std::endl;
		t->expires_at(t->expires_at() + boost::posix_time::seconds(1));
		t->async_wait(boost::bind(
		                  print,
		                  boost::asio::placeholders::error,
		                  t,
		                  count
		              ));
	}
}

int main(int argc, char *argv[])
{
	boost::asio::io_service io;

	int count = 0;
	boost::asio::deadline_timer t(io, boost::posix_time::seconds(1));
	t.async_wait(boost::bind(
	                 print,
	                 boost::asio::placeholders::error,
	                 &t,
	                 &count
	             ));

	std::cout << "Meantime stuff" << std::endl;
	io.run();

	return 0;
}
<|endoftext|>


<commit_before>/**
 * @file rodserrorwindow.h
 * @brief Implementation of class RodsErrorWindow
 *
 * The RodsErrorWindow class extends the Qt widget base class QWidget
 * and implements a error list display window
 *
 * Copyright (C) 2014-2015 University of Jyväskylä. All rights reserved.
 * License: The BSD 3-Clause License, see LICENSE file for details.
 *
 * @author Ilari Korhonen
 */

#include "rodserrorlogwindow.h"

RodsErrorLogWindow::RodsErrorLogWindow() :
    QWidget(NULL)
{
    this->setWindowTitle("iRODS Client Error Log");
    this->setFixedWidth(600);

    this->layout = new QVBoxLayout(this);

    this->errorLog = new QListWidget(this);
    this->layout->addWidget(this->errorLog);

    this->ackButton = new QPushButton("Acknowledge", this);
    this->layout->addWidget(this->ackButton);

    this->warnIcon = QIcon(":/tango/icons/dialog-warning.svg");
}

RodsErrorLogWindow::~RodsErrorLogWindow()
{
    delete (this->layout);
    delete (this->errorLog);
    delete (this->ackButton);
}

void RodsErrorLogWindow::logError(QString msgStr, QString errorStr, int errorCode)
{
    QString itemStr = QDateTime::currentDateTime().toString() + "\n";
    itemStr += msgStr;

    if (errorStr.length())
        itemStr += "\nError Description: " + errorStr;

    itemStr += "\nError Code: " + QVariant(errorCode).toString();

    QListWidgetItem *item = new QListWidgetItem(this->warnIcon, itemStr, this->errorLog);
    this->errorLog->insertItem(0, item);

    this->show();
    this->raise();

    QApplication::setActiveWindow(this);
}
<commit_msg>RodsErrorLogWindow ui adjustments<commit_after>/**
 * @file rodserrorwindow.h
 * @brief Implementation of class RodsErrorWindow
 *
 * The RodsErrorWindow class extends the Qt widget base class QWidget
 * and implements a error list display window
 *
 * Copyright (C) 2014-2015 University of Jyväskylä. All rights reserved.
 * License: The BSD 3-Clause License, see LICENSE file for details.
 *
 * @author Ilari Korhonen
 */

#include "rodserrorlogwindow.h"

RodsErrorLogWindow::RodsErrorLogWindow() :
    QWidget(NULL)
{
    this->setWindowTitle("iRODS Client Error Log");
    this->setMinimumWidth(600);

    this->layout = new QVBoxLayout(this);

    this->errorLog = new QListWidget(this);
    this->layout->addWidget(this->errorLog);

    this->ackButton = new QPushButton("Acknowledge", this);
    this->layout->addWidget(this->ackButton);

    this->warnIcon = QIcon(":/tango/icons/dialog-warning.svg");
}

RodsErrorLogWindow::~RodsErrorLogWindow()
{
    delete (this->layout);
    delete (this->errorLog);
    delete (this->ackButton);
}

void RodsErrorLogWindow::logError(QString msgStr, QString errorStr, int errorCode)
{
    QString itemStr = QDateTime::currentDateTime().toString() + "\n";
    itemStr += msgStr;

    if (errorStr.length())
        itemStr += "\nError Description: " + errorStr;

    itemStr += "\nError Code: " + QVariant(errorCode).toString();

    QListWidgetItem *item = new QListWidgetItem(this->warnIcon, itemStr, this->errorLog);
    this->errorLog->insertItem(0, item);
    this->errorLog->scrollToItem(item);

    this->show();
    this->raise();

    QApplication::setActiveWindow(this);
}
<|endoftext|>


<commit_before>/*-
 * Copyright (c) 2008 Michael Marner <michael@20papercups.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.  * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <math.h>
#include <cstdlib>
#include <config.h>
#include <sstream>
#include <wcl/geometry/Line.h>
#include <wcl/Exception.h>

namespace wcl
{
	Line::Line(const wcl::Vector& position, const wcl::Vector& direction)
		: pos(position), dir(direction)
	{
		//just in case it's not a unit vector
		this->dir = this->dir.unit();
	}

	Line::Line(const Line& l)
	{
		this->pos = l.pos;
		this->dir = l.dir;
	}

	wcl::Vector Line::getPosition()
	{
		return pos;
	}

	wcl::Vector Line::getDirection()
	{
		return dir;
	}

	std::string Line::toString()
	{
		std::stringstream ss;
		ss << "Line. Position: (" << pos[0] << ", " << pos[1] << ", " << pos[2] << ") ";
		ss << "Direction: (" << dir[0] << ", " << dir[1] << ", " << dir[2] << ")" << std::endl;

		return ss.str();
	}

	double Line::distanceFromPoint(const wcl::Vector& p)
	{
		return (this->pos - p).normal();
	}

	wcl::Vector Line::intersect(const wcl::Line& l)
	{
		double t;
		if (fabs(dir[1] * l.dir[0] - dir[0] * l.dir[1]) > TOL)
		{
			t = (-pos[1]*l.dir[0] +
			      l.pos[1]*l.dir[0] +
				  l.dir[1]*pos[0] -
				  l.dir[1]*l.pos[0]) /
				(dir[1]*l.dir[0] - dir[0]*l.dir[1]);
		}
		else if (fabs(-dir[0] * l.dir[2] + dir[2]*l.dir[0]) > TOL)
		{
			t = -(-l.dir[2]*pos[0] +
				  l.dir[2]*l.pos[0] +
				  l.dir[0]*pos[2] -
				  l.dir[0]*l.pos[2]) /
				(-dir[0]*l.dir[2]+dir[2]*l.dir[0]);
		}
		else if (fabs(-dir[2]*l.dir[1] + dir[1]*l.dir[2]) > TOL)
		{
			t = (pos[2]*l.dir[1] -
				 l.pos[2]*l.dir[1] -
				 l.dir[2]*pos[1] +
				 l.dir[2]*l.pos[1]) /
				(-dir[2]*l.dir[1] + dir[1]*l.dir[2]);
		}
		else
		{
			throw Exception("No Intersection!");
		}

		double x = pos[0] + dir[0]*t;
		double y = pos[1] + dir[1]*t;
		double z = pos[2] + dir[2]*t;

		return wcl::Vector(x,y,z);
	}

	wcl::Vector Line::intersect(const wcl::Plane& p)
	{
		wcl::Vector normal = p.getNormal();
		wcl::Vector point = p.getPosition();
		double a = normal[0];
		double b = normal[1];
		double c = normal[2];
		double d = -(normal[0]*point[0] + normal[1]*point[1] + normal[2]*point[2]);

		double numerator = a*pos[0] + b*pos[1] + c*pos[2] + d;
		double denominator = a*dir[0] + b*dir[1] + c*dir[2];

		if (fabs(denominator) < TOL)
		{
			if (fabs(numerator) < TOL)
			{
				return pos;
			}
			else
			{
				throw Exception("No Intersection!");
			}
		}
		else
		{
			double t = -numerator/denominator;
			wcl::Vector result;
			result.setSize(3);
			result[0] = pos[0] + t*dir[0];
			result[1] = pos[1] + t*dir[1];
			result[2] = pos[2] + t*dir[2];

			return result;
		}
	}

	void Line::perturbDirection()
	{
		dir[0] += 1e-5*(((double)rand())/ RAND_MAX);
		dir[1] += 1e-5*(((double)rand())/ RAND_MAX);
		dir[2] += 1e-5*(((double)rand())/ RAND_MAX);
	}
}

<commit_msg>Line-Plane intersection was wrong.<commit_after>/*-
 * Copyright (c) 2008 Michael Marner <michael@20papercups.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.  * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <math.h>
#include <cstdlib>
#include <config.h>
#include <sstream>
#include <wcl/geometry/Line.h>
#include <wcl/Exception.h>

namespace wcl
{
	Line::Line(const wcl::Vector& position, const wcl::Vector& direction)
		: pos(position), dir(direction)
	{
		//just in case it's not a unit vector
		this->dir = this->dir.unit();
	}

	Line::Line(const Line& l)
	{
		this->pos = l.pos;
		this->dir = l.dir;
	}

	wcl::Vector Line::getPosition()
	{
		return pos;
	}

	wcl::Vector Line::getDirection()
	{
		return dir;
	}

	std::string Line::toString()
	{
		std::stringstream ss;
		ss << "Line. Position: (" << pos[0] << ", " << pos[1] << ", " << pos[2] << ") ";
		ss << "Direction: (" << dir[0] << ", " << dir[1] << ", " << dir[2] << ")" << std::endl;

		return ss.str();
	}

	double Line::distanceFromPoint(const wcl::Vector& p)
	{
		return (this->pos - p).normal();
	}

	wcl::Vector Line::intersect(const wcl::Line& l)
	{
		double t;
		if (fabs(dir[1] * l.dir[0] - dir[0] * l.dir[1]) > TOL)
		{
			t = (-pos[1]*l.dir[0] +
			      l.pos[1]*l.dir[0] +
				  l.dir[1]*pos[0] -
				  l.dir[1]*l.pos[0]) /
				(dir[1]*l.dir[0] - dir[0]*l.dir[1]);
		}
		else if (fabs(-dir[0] * l.dir[2] + dir[2]*l.dir[0]) > TOL)
		{
			t = -(-l.dir[2]*pos[0] +
				  l.dir[2]*l.pos[0] +
				  l.dir[0]*pos[2] -
				  l.dir[0]*l.pos[2]) /
				(-dir[0]*l.dir[2]+dir[2]*l.dir[0]);
		}
		else if (fabs(-dir[2]*l.dir[1] + dir[1]*l.dir[2]) > TOL)
		{
			t = (pos[2]*l.dir[1] -
				 l.pos[2]*l.dir[1] -
				 l.dir[2]*pos[1] +
				 l.dir[2]*l.pos[1]) /
				(-dir[2]*l.dir[1] + dir[1]*l.dir[2]);
		}
		else
		{
			throw Exception("No Intersection!");
		}

		double x = pos[0] + dir[0]*t;
		double y = pos[1] + dir[1]*t;
		double z = pos[2] + dir[2]*t;

		return wcl::Vector(x,y,z);
	}

	wcl::Vector Line::intersect(const wcl::Plane& p)
	{
        wcl::Vector normal = p.getNormal();
        float nDotPos = normal.dot(pos);
        float nDotDir = normal.dot(dir);

        // Denominator: nDotDir.
        // Numerator: (p.getD() - nDotPos)

        // If the denominator is 0, we're either on the plane or
        //  parallel to it.

        float denominator = nDotDir;
        float numerator = (p.getD() - nDotPos);

        if ( fabs(denominator) < TOL )
            if ( fabs(numerator) < TOL ) // On the plane.
                return pos;
            else // Parallel to plane.
                throw Exception("No intersection.");

        // So now we're sure we have a single intersection point.
        // Find the distance from the line position, and return it.
        return pos + ((numerator / denominator) * dir);
	}

	void Line::perturbDirection()
	{
		dir[0] += 1e-5*(((double)rand())/ RAND_MAX);
		dir[1] += 1e-5*(((double)rand())/ RAND_MAX);
		dir[2] += 1e-5*(((double)rand())/ RAND_MAX);
	}
}

<|endoftext|>