Files
mfem/fem/doftrans.cpp
T

555 lines
12 KiB
C++

// Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#include "fem.hpp"
namespace mfem
{
void DofTransformation::TransformPrimal(Vector &v) const
{
TransformPrimal(v.GetData());
}
void DofTransformation::TransformPrimalCols(DenseMatrix &V) const
{
for (int c=0; c<V.Width(); c++)
{
TransformPrimal(V.GetColumn(c));
}
}
void DofTransformation::TransformDual(Vector &v) const
{
TransformDual(v.GetData());
}
void DofTransformation::TransformDual(DenseMatrix &V) const
{
TransformDualCols(V);
TransformDualRows(V);
}
void DofTransformation::TransformDualRows(DenseMatrix &V) const
{
Vector row;
for (int r=0; r<V.Height(); r++)
{
V.GetRow(r, row);
TransformDual(row);
V.SetRow(r, row);
}
}
void DofTransformation::TransformDualCols(DenseMatrix &V) const
{
for (int c=0; c<V.Width(); c++)
{
TransformDual(V.GetColumn(c));
}
}
void DofTransformation::InvTransformPrimal(Vector &v) const
{
InvTransformPrimal(v.GetData());
}
void TransformPrimal(const DofTransformation *ran_dof_trans,
const DofTransformation *dom_dof_trans,
DenseMatrix &elmat)
{
if (ran_dof_trans && dom_dof_trans)
{
ran_dof_trans->TransformPrimalCols(elmat);
dom_dof_trans->TransformDualRows(elmat);
}
else if (ran_dof_trans)
{
ran_dof_trans->TransformPrimalCols(elmat);
}
else if (dom_dof_trans)
{
dom_dof_trans->TransformDualRows(elmat);
}
else
{
// If both transformations are NULL this function should not be called
}
}
void DofTransformation::InvTransformDual(Vector &v) const
{
InvTransformDual(v.GetData());
}
void TransformDual(const DofTransformation *ran_dof_trans,
const DofTransformation *dom_dof_trans,
DenseMatrix &elmat)
{
if (ran_dof_trans && dom_dof_trans)
{
ran_dof_trans->TransformDualCols(elmat);
dom_dof_trans->TransformDualRows(elmat);
}
else if (ran_dof_trans)
{
ran_dof_trans->TransformDualCols(elmat);
}
else if (dom_dof_trans)
{
dom_dof_trans->TransformDualRows(elmat);
}
else
{
// If both transformations are NULL this function should not be called
}
}
void VDofTransformation::TransformPrimal(double *v) const
{
int size = doftrans_->Size();
if ((Ordering::Type)ordering_ == Ordering::byNODES || vdim_ == 1)
{
for (int i=0; i<vdim_; i++)
{
doftrans_->TransformPrimal(&v[i*size]);
}
}
else
{
Vector vec(size);
for (int i=0; i<vdim_; i++)
{
for (int j=0; j<size; j++)
{
vec(j) = v[j*vdim_+i];
}
doftrans_->TransformPrimal(vec);
for (int j=0; j<size; j++)
{
v[j*vdim_+i] = vec(j);
}
}
}
}
void VDofTransformation::InvTransformPrimal(double *v) const
{
int size = doftrans_->Height();
if ((Ordering::Type)ordering_ == Ordering::byNODES)
{
for (int i=0; i<vdim_; i++)
{
doftrans_->InvTransformPrimal(&v[i*size]);
}
}
else
{
Vector vec(size);
for (int i=0; i<vdim_; i++)
{
for (int j=0; j<size; j++)
{
vec(j) = v[j*vdim_+i];
}
doftrans_->InvTransformPrimal(vec);
for (int j=0; j<size; j++)
{
v[j*vdim_+i] = vec(j);
}
}
}
}
void VDofTransformation::TransformDual(double *v) const
{
int size = doftrans_->Size();
if ((Ordering::Type)ordering_ == Ordering::byNODES)
{
for (int i=0; i<vdim_; i++)
{
doftrans_->TransformDual(&v[i*size]);
}
}
else
{
Vector vec(size);
for (int i=0; i<vdim_; i++)
{
for (int j=0; j<size; j++)
{
vec(j) = v[j*vdim_+i];
}
doftrans_->TransformDual(vec);
for (int j=0; j<size; j++)
{
v[j*vdim_+i] = vec(j);
}
}
}
}
void VDofTransformation::InvTransformDual(double *v) const
{
int size = doftrans_->Size();
if ((Ordering::Type)ordering_ == Ordering::byNODES)
{
for (int i=0; i<vdim_; i++)
{
doftrans_->InvTransformDual(&v[i*size]);
}
}
else
{
Vector vec(size);
for (int i=0; i<vdim_; i++)
{
for (int j=0; j<size; j++)
{
vec(j) = v[j*vdim_+i];
}
doftrans_->InvTransformDual(vec);
for (int j=0; j<size; j++)
{
v[j*vdim_+i] = vec(j);
}
}
}
}
const double ND_DofTransformation::T_data[24] =
{
1.0, 0.0, 0.0, 1.0,
-1.0, -1.0, 0.0, 1.0,
0.0, 1.0, -1.0, -1.0,
1.0, 0.0, -1.0, -1.0,
-1.0, -1.0, 1.0, 0.0,
0.0, 1.0, 1.0, 0.0
};
const DenseTensor ND_DofTransformation
::T(const_cast<double*>(ND_DofTransformation::T_data), 2, 2, 6);
const double ND_DofTransformation::TInv_data[24] =
{
1.0, 0.0, 0.0, 1.0,
-1.0, -1.0, 0.0, 1.0,
-1.0, -1.0, 1.0, 0.0,
1.0, 0.0, -1.0, -1.0,
0.0, 1.0, -1.0, -1.0,
0.0, 1.0, 1.0, 0.0
};
const DenseTensor ND_DofTransformation
::TInv(const_cast<double*>(TInv_data), 2, 2, 6);
ND_DofTransformation::ND_DofTransformation(int size, int p)
: DofTransformation(size)
, order(p)
, nedofs(p)
, nfdofs(p*(p-1))
{
}
ND_TriDofTransformation::ND_TriDofTransformation(int p)
: ND_DofTransformation(p*(p + 2), p)
{
}
void ND_TriDofTransformation::TransformPrimal(double *v) const
{
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 1,
"Face orientations are unset in ND_TriDofTransformation");
double data[2];
Vector v2(data, 2);
// Transform face DoFs
for (int f=0; f<1; f++)
{
for (int i=0; i<nfdofs/2; i++)
{
v2 = &v[3*nedofs + f*nfdofs + 2*i];
T(Fo[f]).Mult(v2, &v[3*nedofs + f*nfdofs + 2*i]);
}
}
}
void
ND_TriDofTransformation::InvTransformPrimal(double *v) const
{
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 1,
"Face orientations are unset in ND_TriDofTransformation");
double data[2];
Vector v2(data, 2);
// Transform face DoFs
for (int f=0; f<1; f++)
{
for (int i=0; i<nfdofs/2; i++)
{
v2 = &v[3*nedofs + f*nfdofs + 2*i];
TInv(Fo[f]).Mult(v2, &v[3*nedofs + f*nfdofs + 2*i]);
}
}
}
void
ND_TriDofTransformation::TransformDual(double *v) const
{
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 1,
"Face orientations are unset in ND_TriDofTransformation");
double data[2];
Vector v2(data, 2);
// Transform face DoFs
for (int f=0; f<1; f++)
{
for (int i=0; i<nfdofs/2; i++)
{
v2 = &v[3*nedofs + f*nfdofs + 2*i];
TInv(Fo[f]).MultTranspose(v2, &v[3*nedofs + f*nfdofs + 2*i]);
}
}
}
void
ND_TriDofTransformation::InvTransformDual(double *v) const
{
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 1,
"Face orientations are unset in ND_TriDofTransformation");
double data[2];
Vector v2(data, 2);
// Transform face DoFs
for (int f=0; f<1; f++)
{
for (int i=0; i<nfdofs/2; i++)
{
v2 = &v[3*nedofs + f*nfdofs + 2*i];
T(Fo[f]).MultTranspose(v2, &v[3*nedofs + f*nfdofs + 2*i]);
}
}
}
ND_TetDofTransformation::ND_TetDofTransformation(int p)
: ND_DofTransformation(p*(p + 2)*(p + 3)/2, p)
{
}
void ND_TetDofTransformation::TransformPrimal(double *v) const
{
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 4,
"Face orientations are unset in ND_TetDofTransformation");
double data[2];
Vector v2(data, 2);
// Transform face DoFs
for (int f=0; f<4; f++)
{
for (int i=0; i<nfdofs/2; i++)
{
v2 = &v[6*nedofs + f*nfdofs + 2*i];
T(Fo[f]).Mult(v2, &v[6*nedofs + f*nfdofs + 2*i]);
}
}
}
void
ND_TetDofTransformation::InvTransformPrimal(double *v) const
{
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 4,
"Face orientations are unset in ND_TetDofTransformation");
double data[2];
Vector v2(data, 2);
// Transform face DoFs
for (int f=0; f<4; f++)
{
for (int i=0; i<nfdofs/2; i++)
{
v2 = &v[6*nedofs + f*nfdofs + 2*i];
TInv(Fo[f]).Mult(v2, &v[6*nedofs + f*nfdofs + 2*i]);
}
}
}
void
ND_TetDofTransformation::TransformDual(double *v) const
{
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 4,
"Face orientations are unset in ND_TetDofTransformation");
double data[2];
Vector v2(data, 2);
// Transform face DoFs
for (int f=0; f<4; f++)
{
for (int i=0; i<nfdofs/2; i++)
{
v2 = &v[6*nedofs + f*nfdofs + 2*i];
TInv(Fo[f]).MultTranspose(v2, &v[6*nedofs + f*nfdofs + 2*i]);
}
}
}
void
ND_TetDofTransformation::InvTransformDual(double *v) const
{
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 4,
"Face orientations are unset in ND_TetDofTransformation");
double data[2];
Vector v2(data, 2);
// Transform face DoFs
for (int f=0; f<4; f++)
{
for (int i=0; i<nfdofs/2; i++)
{
v2 = &v[6*nedofs + f*nfdofs + 2*i];
T(Fo[f]).MultTranspose(v2, &v[6*nedofs + f*nfdofs + 2*i]);
}
}
}
ND_WedgeDofTransformation::ND_WedgeDofTransformation(int p)
: ND_DofTransformation(3 * p * ((p + 1) * (p + 2))/2, p)
{
}
void ND_WedgeDofTransformation::TransformPrimal(double *v) const
{
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 2,
"Face orientations are unset in ND_WedgeDofTransformation");
double data[2];
Vector v2(data, 2);
// Transform triangular face DoFs
for (int f=0; f<2; f++)
{
for (int i=0; i<nfdofs/2; i++)
{
v2 = &v[9*nedofs + f*nfdofs + 2*i];
T(Fo[f]).Mult(v2, &v[9*nedofs + f*nfdofs + 2*i]);
}
}
}
void
ND_WedgeDofTransformation::InvTransformPrimal(double *v) const
{
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 2,
"Face orientations are unset in ND_WedgeDofTransformation");
double data[2];
Vector v2(data, 2);
// Transform triangular face DoFs
for (int f=0; f<2; f++)
{
for (int i=0; i<nfdofs/2; i++)
{
v2 = &v[9*nedofs + f*nfdofs + 2*i];
TInv(Fo[f]).Mult(v2, &v[9*nedofs + f*nfdofs + 2*i]);
}
}
}
void
ND_WedgeDofTransformation::TransformDual(double *v) const
{
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 2,
"Face orientations are unset in ND_WedgeDofTransformation");
double data[2];
Vector v2(data, 2);
// Transform triangular face DoFs
for (int f=0; f<2; f++)
{
for (int i=0; i<nfdofs/2; i++)
{
v2 = &v[9*nedofs + f*nfdofs + 2*i];
TInv(Fo[f]).MultTranspose(v2, &v[9*nedofs + f*nfdofs + 2*i]);
}
}
}
void
ND_WedgeDofTransformation::InvTransformDual(double *v) const
{
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 2,
"Face orientations are unset in ND_WedgeDofTransformation");
double data[2];
Vector v2(data, 2);
// Transform triangular face DoFs
for (int f=0; f<2; f++)
{
for (int i=0; i<nfdofs/2; i++)
{
v2 = &v[9*nedofs + f*nfdofs + 2*i];
T(Fo[f]).MultTranspose(v2, &v[9*nedofs + f*nfdofs + 2*i]);
}
}
}
} // namespace mfem