Liebe Gitlab-Nutzer, lieber Gitlab-Nutzer, es ist nun möglich sich mittels des ZIH-Logins/LDAP an unserem Dienst anzumelden. Die Konto der externen Nutzer:innen sind über den Reiter "Standard" erreichbar. Die Administratoren

Dear Gitlab user, it is now possible to log in to our service using the ZIH login/LDAP. The accounts of external users can be accessed via the "Standard" tab. The administrators

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

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