Commit aeaa15ee authored by Praetorius, Simon's avatar Praetorius, Simon

allow lambda functiosn in Dirichlet BC

parent 013c2859
......@@ -97,7 +97,7 @@ SET(AMDIS_SRC ${SOURCE_DIR}/AdaptBase.cc
${SOURCE_DIR}/DOFMatrix.cc
${SOURCE_DIR}/DOFVector.cc
${SOURCE_DIR}/Debug.cc
# ${SOURCE_DIR}/DirichletBC.cc
${SOURCE_DIR}/DirichletBC.cc
${SOURCE_DIR}/DualTraverse.cc
${SOURCE_DIR}/ElInfo.cc
${SOURCE_DIR}/ElInfo1d.cc
......
......@@ -26,77 +26,89 @@
#include "DOFMatrix.h"
namespace AMDiS {
DirichletBC::DirichletBC(BoundaryType type,
AbstractFunction<double, WorldVector<double> > *fct,
const FiniteElemSpace *rowFeSpace,
const FiniteElemSpace *colFeSpace,
bool apply)
: BoundaryCondition(type, rowFeSpace, colFeSpace),
f(fct),
dofVec(NULL),
applyBC(apply)
{}
DirichletBC::DirichletBC(BoundaryType type,
DOFVectorBase<double> *vec,
bool apply)
: BoundaryCondition(type, vec->getFeSpace(), vec->getFeSpace()),
f(NULL),
dofVec(vec),
applyBC(apply)
{}
void DirichletBC::fillBoundaryCondition(DOFMatrix* matrix,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts)
namespace detail {
void DirichletBC::fillBoundaryCondition(DOFMatrix* matrix,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts)
{
FUNCNAME_DBG("DirichletBC::fillBoundaryCondition()");
TEST_EXIT_DBG(matrix->getRowFeSpace() == rowFeSpace)("invalid row fe space\n");
}
void DirichletBC::initVector(DOFVectorBase<double>* vec)
{
if (dynamic_cast<DOFVector<double>*>(vec))
dynamic_cast<DOFVector<double>*>(vec)->getDirichletValues().clear();
}
}
DirichletBC<_value_by_dofvector>::DirichletBC(
BoundaryType type,
DOFVectorBase<double> *vec,
bool apply)
: super(type, vec->getFeSpace(), vec->getFeSpace(), apply),
container(vec)
{ }
void DirichletBC<_value_by_dofvector>::fillBoundaryCondition(
DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts)
{
FUNCNAME_DBG("DirichletBC::fillBoundaryCondition()");
TEST_EXIT_DBG(matrix->getRowFeSpace() == rowFeSpace)("invalid row fe space\n");
for (int i = 0; i < nBasFcts; i++)
if (localBound[i] == boundaryType) {
double value = (*container)[dofIndices[i]];
vector->setDirichletDofValue(dofIndices[i], value);
(*vector)[dofIndices[i]] = value;
}
}
void DirichletBC::fillBoundaryCondition(DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts)
// c++11 std::function of lambda-functions
void DirichletBC<_value_by_function>::fillBoundaryCondition(
DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts)
{
FUNCNAME("DirichletBC::fillBoundaryCondition()");
TEST_EXIT_DBG(vector->getFeSpace() == rowFeSpace)("invalid row fe space\n");
WorldVector<double> worldCoords;
const BasisFunction *basFcts = rowFeSpace->getBasisFcts();
if (f) {
for (int i = 0; i < nBasFcts; i++)
if (localBound[i] == boundaryType) {
elInfo->coordToWorld(*(basFcts->getCoords(i)), worldCoords);
double value = (*f)(worldCoords);
vector->setDirichletDofValue(dofIndices[i], value);
(*vector)[dofIndices[i]] = value;
}
} else if (dofVec) {
for (int i = 0; i < nBasFcts; i++)
if (localBound[i] == boundaryType) {
double value = value = (*dofVec)[dofIndices[i]];
vector->setDirichletDofValue(dofIndices[i], value);
(*vector)[dofIndices[i]] = value;
}
} else {
ERROR_EXIT("No data provided to assemble DirichletBC!\n");
}
for (int i = 0; i < nBasFcts; i++)
if (localBound[i] == boundaryType) {
elInfo->coordToWorld(*(basFcts->getCoords(i)), worldCoords);
double value = container(worldCoords);
vector->setDirichletDofValue(dofIndices[i], value);
(*vector)[dofIndices[i]] = value;
}
}
void DirichletBC::initVector(DOFVectorBase<double>* vec)
void DirichletBC<_value_by_abstractfunction>::fillBoundaryCondition(
DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts)
{
if (dynamic_cast<DOFVector<double>*>(vec))
dynamic_cast<DOFVector<double>*>(vec)->getDirichletValues().clear();
}
WorldVector<double> worldCoords;
const BasisFunction *basFcts = rowFeSpace->getBasisFcts();
for (int i = 0; i < nBasFcts; i++)
if (localBound[i] == boundaryType) {
elInfo->coordToWorld(*(basFcts->getCoords(i)), worldCoords);
double value = container(worldCoords);
vector->setDirichletDofValue(dofIndices[i], value);
(*vector)[dofIndices[i]] = value;
}
}
}
......@@ -40,142 +40,155 @@ namespace AMDiS
namespace detail
{
template <class Tag>
struct ValueContainer {};
class DirichletBC : public BoundaryCondition
{
public:
/// Constructor.
DirichletBC(BoundaryType type,
const FiniteElemSpace *rowFeSpace,
const FiniteElemSpace *colFeSpace,
bool apply)
: BoundaryCondition(type, rowFeSpace, colFeSpace),
applyBC(apply)
{ }
/// Implementation of BoundaryCondition::fillBoundaryCondition().
virtual void fillBoundaryCondition(DOFMatrix* matrix,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts) override;
///
void initVector(DOFVectorBase<double>* vec);
/// Implementation of BoundaryCondition::boundResidual().
double boundResidual(ElInfo*,
DOFMatrix *,
const DOFVectorBase<double>*)
{
return 0.0;
}
/// Because this is a Dirichlet boundary condition, always return true.
bool isDirichlet()
{
return true;
}
/// Returns \ref applyBC.
bool applyBoundaryCondition()
{
return applyBC;
}
protected:
/// Defines, if the boundary condition must be applied to the matrix. See
/// comment of \ref BoundaryCondition::applyBoundaryCondition.
bool applyBC;
};
} // end namespace detail
/**
* \ingroup Assembler
*
* \brief
* Sub class of BoundaryCondition. Implements Dirichlet boundary conditions.
* A DOFVectors is set to a given value at a Dirichlet dof and in a DOFMatrix
* the row corresponding to a Dirichlet dof is replaced by a row containing
* only a 1.0 in the diagonal.
*/
template <class ValueTag>
class DirichletBC {};
// specialization for AbstractFunctions as value container
template <>
struct ValueContainer<_value_by_abstractfunction>
class DirichletBC<_value_by_abstractfunction> : public detail::DirichletBC
{
ValueContainer(AbstractFunction<double, WorldVector<double> > *fct) : value(*fct) {};
ValueContainer(AbstractFunction<double, WorldVector<double> > &fct) : value(fct) {};
typedef detail::DirichletBC super;
public:
/// Constructor.
DirichletBC(BoundaryType type,
AbstractFunction<double, WorldVector<double> > *fct,
const FiniteElemSpace *rowFeSpace,
const FiniteElemSpace *colFeSpace = NULL,
bool apply = true)
: super(type, rowFeSpace, colFeSpace, apply),
container(*fct)
{ }
AbstractFunction<double, WorldVector<double> > &value;
/// Implementation of BoundaryCondition::fillBoundaryCondition().
virtual void fillBoundaryCondition(DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts) override;
protected:
AbstractFunction<double, WorldVector<double> > &container;
};
// specialization for DOFVectors as value container
template <>
struct ValueContainer<_value_by_dofvector>
class DirichletBC<_value_by_dofvector> : public detail::DirichletBC
{
ValueContainer(DOFVectorBase<double> *vec) : value(vec) {};
ValueContainer(DOFVectorBase<double> &vec) : value(&vec) {};
typedef detail::DirichletBC super;
public:
/// Constructor.
DirichletBC(BoundaryType type,
DOFVectorBase<double> *vec,
bool apply = true);
DOFVectorBase<double> *value;
/// Implementation of BoundaryCondition::fillBoundaryCondition().
virtual void fillBoundaryCondition(DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts) override;
protected:
DOFVectorBase<double> *container;
};
#if __cplusplus > 199711L
// specialization for std::function or lambdas as value container
template <>
struct ValueContainer<_value_by_function>
class DirichletBC<_value_by_function> : public detail::DirichletBC
{
ValueContainer(std::function<double(WorldVector<double>)> fct) : value(fct) {};
typedef detail::DirichletBC super;
public:
/// Constructor.
DirichletBC(BoundaryType type,
std::function<double(WorldVector<double>)> fct,
const FiniteElemSpace *rowFeSpace,
const FiniteElemSpace *colFeSpace = NULL,
bool apply = true)
: super(type, rowFeSpace, colFeSpace, apply),
container(fct)
{ }
std::function<double(WorldVector<double>)> value;
/// Implementation of BoundaryCondition::fillBoundaryCondition().
virtual void fillBoundaryCondition(DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts) override;
protected:
std::function<double(WorldVector<double>)> container;
};
#endif
} // end namespace detail
/**
* \ingroup Assembler
*
* \brief
* Sub class of BoundaryCondition. Implements Dirichlet boundary conditions.
* A DOFVectors is set to a given value at a Dirichlet dof and in a DOFMatrix
* the row corresponding to a Dirichlet dof is replaced by a row containing
* only a 1.0 in the diagonal.
*/
template <class ValueTag>
class DirichletBC : public BoundaryCondition
{
public:
/// Constructor.
DirichletBC(BoundaryType type,
AbstractFunction<double, WorldVector<double> > *fct,
const FiniteElemSpace *rowFeSpace,
const FiniteElemSpace *colFeSpace = NULL,
bool apply = true);
#if __cplusplus > 199711L
/// Constructor.
DirichletBC(BoundaryType type,
std::function<double(WorldVector<double>)> fct,
const FiniteElemSpace *rowFeSpace,
const FiniteElemSpace *colFeSpace = NULL,
bool apply = true);
#endif
/// Constructor.
DirichletBC(BoundaryType type,
DOFVectorBase<double> *vec,
bool apply = true);
/// Implementation of BoundaryCondition::fillBoundaryCondition().
virtual void fillBoundaryCondition(DOFMatrix* matrix,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts) override;
/// Implementation of BoundaryCondition::fillBoundaryCondition().
virtual void fillBoundaryCondition(DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts) override;
///
void initVector(DOFVectorBase<double>*);
/// Implementation of BoundaryCondition::boundResidual().
double boundResidual(ElInfo*,
DOFMatrix *,
const DOFVectorBase<double>*)
{
return 0.0;
}
/// Because this is a Dirichlet boundary condition, always return true.
bool isDirichlet()
{
return true;
}
/// Returns \ref applyBC.
bool applyBoundaryCondition()
{
return applyBC;
}
protected:
void fillBC(_value_by_abstractfunction,
DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts);
void fillBC(_value_by_function,
DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts);
void fillBC(_value_by_dofvector,
DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts);
protected:
detail::ValueContainer<ValueTag> container;
/// Defines, if the boundary condition must be applied to the matrix. See
/// comment of \ref BoundaryCondition::applyBoundaryCondition.
bool applyBC;
};
}
#include "DirichletBC.hh"
#endif
/******************************************************************************
*
* AMDiS - Adaptive multidimensional simulations
*
* Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
* Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
*
* Authors:
* Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
*
* This file is part of AMDiS
*
* See also license.opensource.txt in the distribution.
*
******************************************************************************/
#include "ElInfo.h"
#include "BasisFunction.h"
#include "DOFVector.h"
#include "DOFMatrix.h"
namespace AMDiS {
template <class Tag>
DirichletBC<Tag>::DirichletBC(BoundaryType type,
AbstractFunction<double, WorldVector<double> > *fct,
const FiniteElemSpace *rowFeSpace,
const FiniteElemSpace *colFeSpace,
bool apply)
: BoundaryCondition(type, rowFeSpace, colFeSpace),
container(fct),
applyBC(apply)
{}
#if __cplusplus > 199711L
template <class Tag>
DirichletBC<Tag>::DirichletBC(BoundaryType type,
std::function<double(WorldVector<double>)> fct,
const FiniteElemSpace *rowFeSpace,
const FiniteElemSpace *colFeSpace,
bool apply)
: BoundaryCondition(type, rowFeSpace, colFeSpace),
container(fct),
applyBC(apply)
{}
#endif
template <class Tag>
DirichletBC<Tag>::DirichletBC(BoundaryType type,
DOFVectorBase<double> *vec,
bool apply)
: BoundaryCondition(type, vec->getFeSpace(), vec->getFeSpace()),
container(vec),
applyBC(apply)
{}
template <class Tag>
void DirichletBC<Tag>::fillBoundaryCondition(DOFMatrix* matrix,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts)
{
FUNCNAME_DBG("DirichletBC::fillBoundaryCondition()");
TEST_EXIT_DBG(matrix->getRowFeSpace() == rowFeSpace)("invalid row fe space\n");
}
template <class Tag>
void DirichletBC<Tag>::fillBoundaryCondition(DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts)
{
FUNCNAME_DBG("DirichletBC::fillBoundaryCondition()");
TEST_EXIT_DBG(vector->getFeSpace() == rowFeSpace)("invalid row fe space\n");
fillBC(Tag(), vector, elInfo, dofIndices, localBound, nBasFcts);
}
template <class Tag>
void DirichletBC<Tag>::fillBC(_value_by_abstractfunction,
DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts)
{
WorldVector<double> worldCoords;
const BasisFunction *basFcts = rowFeSpace->getBasisFcts();
for (int i = 0; i < nBasFcts; i++)
if (localBound[i] == boundaryType) {
elInfo->coordToWorld(*(basFcts->getCoords(i)), worldCoords);
double value = container.value(worldCoords);
vector->setDirichletDofValue(dofIndices[i], value);
(*vector)[dofIndices[i]] = value;
}
}
// c++11 std::function of lambda-functions
template <class Tag>
void DirichletBC<Tag>::fillBC(_value_by_function,
DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts)
{
WorldVector<double> worldCoords;
const BasisFunction *basFcts = rowFeSpace->getBasisFcts();
for (int i = 0; i < nBasFcts; i++)
if (localBound[i] == boundaryType) {
elInfo->coordToWorld(*(basFcts->getCoords(i)), worldCoords);
double value = container.value(worldCoords);
vector->setDirichletDofValue(dofIndices[i], value);
(*vector)[dofIndices[i]] = value;
}
}
template <class Tag>
void DirichletBC<Tag>::fillBC(_value_by_dofvector,
DOFVectorBase<double>* vector,
ElInfo* elInfo,
const DegreeOfFreedom* dofIndices,
const BoundaryType* localBound,
int nBasFcts)
{
for (int i = 0; i < nBasFcts; i++)
if (localBound[i] == boundaryType) {
double value = (*container.value)[dofIndices[i]];
vector->setDirichletDofValue(dofIndices[i], value);
(*vector)[dofIndices[i]] = value;
}
}
template <class Tag>
void DirichletBC<Tag>::initVector(DOFVectorBase<double>* vec)
{
if (dynamic_cast<DOFVector<double>*>(vec))
dynamic_cast<DOFVector<double>*>(vec)->getDirichletValues().clear();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment