829 lines
21 KiB
C++
829 lines
21 KiB
C++
// Copyright (c) 2010-2020, 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 <cmath>
|
|
#include "fem.hpp"
|
|
|
|
namespace mfem
|
|
{
|
|
|
|
void LinearFormIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, FaceElementTransformations &Tr, Vector &elvect)
|
|
{
|
|
mfem_error("LinearFormIntegrator::AssembleRHSElementVect(...)");
|
|
}
|
|
|
|
|
|
void DomainLFIntegrator::AssembleRHSElementVect(const FiniteElement &el,
|
|
ElementTransformation &Tr,
|
|
Vector &elvect)
|
|
{
|
|
int dof = el.GetDof();
|
|
|
|
shape.SetSize(dof); // vector of size dof
|
|
elvect.SetSize(dof);
|
|
elvect = 0.0;
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
// ir = &IntRules.Get(el.GetGeomType(),
|
|
// oa * el.GetOrder() + ob + Tr.OrderW());
|
|
ir = &IntRules.Get(el.GetGeomType(), oa * el.GetOrder() + ob);
|
|
}
|
|
|
|
for (int i = 0; i < ir->GetNPoints(); i++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(i);
|
|
|
|
Tr.SetIntPoint (&ip);
|
|
double val = Tr.Weight() * Q.Eval(Tr, ip);
|
|
|
|
el.CalcShape(ip, shape);
|
|
|
|
add(elvect, ip.weight * val, shape, elvect);
|
|
}
|
|
}
|
|
|
|
void DomainLFIntegrator::AssembleDeltaElementVect(
|
|
const FiniteElement &fe, ElementTransformation &Trans, Vector &elvect)
|
|
{
|
|
MFEM_ASSERT(delta != NULL, "coefficient must be DeltaCoefficient");
|
|
elvect.SetSize(fe.GetDof());
|
|
fe.CalcPhysShape(Trans, elvect);
|
|
elvect *= delta->EvalDelta(Trans, Trans.GetIntPoint());
|
|
}
|
|
|
|
|
|
void BoundaryLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
|
{
|
|
int dof = el.GetDof();
|
|
|
|
shape.SetSize(dof); // vector of size dof
|
|
elvect.SetSize(dof);
|
|
elvect = 0.0;
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
int intorder = oa * el.GetOrder() + ob; // <----------
|
|
ir = &IntRules.Get(el.GetGeomType(), intorder);
|
|
}
|
|
|
|
for (int i = 0; i < ir->GetNPoints(); i++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(i);
|
|
|
|
Tr.SetIntPoint (&ip);
|
|
double val = Tr.Weight() * Q.Eval(Tr, ip);
|
|
|
|
el.CalcShape(ip, shape);
|
|
|
|
add(elvect, ip.weight * val, shape, elvect);
|
|
}
|
|
}
|
|
|
|
void BoundaryLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, FaceElementTransformations &Tr, Vector &elvect)
|
|
{
|
|
int dof = el.GetDof();
|
|
|
|
shape.SetSize(dof); // vector of size dof
|
|
elvect.SetSize(dof);
|
|
elvect = 0.0;
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
int intorder = oa * el.GetOrder() + ob; // <------ user control
|
|
ir = &IntRules.Get(Tr.FaceGeom, intorder); // of integration order
|
|
}
|
|
|
|
for (int i = 0; i < ir->GetNPoints(); i++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(i);
|
|
IntegrationPoint eip;
|
|
Tr.Loc1.Transform(ip, eip);
|
|
|
|
Tr.Face->SetIntPoint (&ip);
|
|
double val = Tr.Face->Weight() * ip.weight * Q.Eval(*Tr.Face, ip);
|
|
|
|
el.CalcShape(eip, shape);
|
|
|
|
add(elvect, val, shape, elvect);
|
|
}
|
|
}
|
|
|
|
void BoundaryNormalLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
|
{
|
|
int dim = el.GetDim()+1;
|
|
int dof = el.GetDof();
|
|
Vector nor(dim), Qvec;
|
|
|
|
shape.SetSize(dof);
|
|
elvect.SetSize(dof);
|
|
elvect = 0.0;
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
int intorder = oa * el.GetOrder() + ob; // <----------
|
|
ir = &IntRules.Get(el.GetGeomType(), intorder);
|
|
}
|
|
|
|
for (int i = 0; i < ir->GetNPoints(); i++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(i);
|
|
|
|
Tr.SetIntPoint(&ip);
|
|
CalcOrtho(Tr.Jacobian(), nor);
|
|
Q.Eval(Qvec, Tr, ip);
|
|
|
|
el.CalcShape(ip, shape);
|
|
|
|
elvect.Add(ip.weight*(Qvec*nor), shape);
|
|
}
|
|
}
|
|
|
|
void BoundaryTangentialLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
|
{
|
|
int dim = el.GetDim()+1;
|
|
int dof = el.GetDof();
|
|
Vector tangent(dim), Qvec;
|
|
|
|
shape.SetSize(dof);
|
|
elvect.SetSize(dof);
|
|
elvect = 0.0;
|
|
|
|
if (dim != 2)
|
|
{
|
|
mfem_error("These methods make sense only in 2D problems.");
|
|
}
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
int intorder = oa * el.GetOrder() + ob; // <----------
|
|
ir = &IntRules.Get(el.GetGeomType(), intorder);
|
|
}
|
|
|
|
for (int i = 0; i < ir->GetNPoints(); i++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(i);
|
|
|
|
Tr.SetIntPoint(&ip);
|
|
const DenseMatrix &Jac = Tr.Jacobian();
|
|
tangent(0) = Jac(0,0);
|
|
tangent(1) = Jac(1,0);
|
|
|
|
Q.Eval(Qvec, Tr, ip);
|
|
|
|
el.CalcShape(ip, shape);
|
|
|
|
add(elvect, ip.weight*(Qvec*tangent), shape, elvect);
|
|
}
|
|
}
|
|
|
|
void VectorDomainLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
|
{
|
|
int vdim = Q.GetVDim();
|
|
int dof = el.GetDof();
|
|
|
|
double val,cf;
|
|
|
|
shape.SetSize(dof); // vector of size dof
|
|
|
|
elvect.SetSize(dof * vdim);
|
|
elvect = 0.0;
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
int intorder = 2*el.GetOrder();
|
|
ir = &IntRules.Get(el.GetGeomType(), intorder);
|
|
}
|
|
|
|
for (int i = 0; i < ir->GetNPoints(); i++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(i);
|
|
|
|
Tr.SetIntPoint (&ip);
|
|
val = Tr.Weight();
|
|
|
|
el.CalcShape(ip, shape);
|
|
Q.Eval (Qvec, Tr, ip);
|
|
|
|
for (int k = 0; k < vdim; k++)
|
|
{
|
|
cf = val * Qvec(k);
|
|
|
|
for (int s = 0; s < dof; s++)
|
|
{
|
|
elvect(dof*k+s) += ip.weight * cf * shape(s);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void VectorDomainLFIntegrator::AssembleDeltaElementVect(
|
|
const FiniteElement &fe, ElementTransformation &Trans, Vector &elvect)
|
|
{
|
|
MFEM_ASSERT(vec_delta != NULL, "coefficient must be VectorDeltaCoefficient");
|
|
int vdim = Q.GetVDim();
|
|
int dof = fe.GetDof();
|
|
|
|
shape.SetSize(dof);
|
|
fe.CalcPhysShape(Trans, shape);
|
|
|
|
vec_delta->EvalDelta(Qvec, Trans, Trans.GetIntPoint());
|
|
|
|
elvect.SetSize(dof*vdim);
|
|
DenseMatrix elvec_as_mat(elvect.GetData(), dof, vdim);
|
|
MultVWt(shape, Qvec, elvec_as_mat);
|
|
}
|
|
|
|
|
|
void VectorBoundaryLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
|
{
|
|
int vdim = Q.GetVDim();
|
|
int dof = el.GetDof();
|
|
|
|
shape.SetSize(dof);
|
|
vec.SetSize(vdim);
|
|
|
|
elvect.SetSize(dof * vdim);
|
|
elvect = 0.0;
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
int intorder = 2*el.GetOrder();
|
|
ir = &IntRules.Get(el.GetGeomType(), intorder);
|
|
}
|
|
|
|
for (int i = 0; i < ir->GetNPoints(); i++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(i);
|
|
|
|
Q.Eval(vec, Tr, ip);
|
|
Tr.SetIntPoint (&ip);
|
|
vec *= Tr.Weight() * ip.weight;
|
|
el.CalcShape(ip, shape);
|
|
for (int k = 0; k < vdim; k++)
|
|
for (int s = 0; s < dof; s++)
|
|
{
|
|
elvect(dof*k+s) += vec(k) * shape(s);
|
|
}
|
|
}
|
|
}
|
|
|
|
void VectorBoundaryLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, FaceElementTransformations &Tr, Vector &elvect)
|
|
{
|
|
int vdim = Q.GetVDim();
|
|
int dof = el.GetDof();
|
|
|
|
shape.SetSize(dof);
|
|
vec.SetSize(vdim);
|
|
|
|
elvect.SetSize(dof * vdim);
|
|
elvect = 0.0;
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
int intorder = 2*el.GetOrder();
|
|
ir = &IntRules.Get(Tr.GetGeometryType(), intorder);
|
|
}
|
|
|
|
for (int i = 0; i < ir->GetNPoints(); i++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(i);
|
|
IntegrationPoint eip;
|
|
Tr.Loc1.Transform(ip, eip);
|
|
|
|
Tr.SetIntPoint(&ip);
|
|
|
|
// Use Tr transformation in case Q depends on boundary attribute
|
|
Q.Eval(vec, Tr, ip);
|
|
vec *= Tr.Weight() * ip.weight;
|
|
el.CalcShape(eip, shape);
|
|
for (int k = 0; k < vdim; k++)
|
|
{
|
|
for (int s = 0; s < dof; s++)
|
|
{
|
|
elvect(dof*k+s) += vec(k) * shape(s);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void VectorFEDomainLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
|
{
|
|
int dof = el.GetDof();
|
|
int spaceDim = Tr.GetSpaceDim();
|
|
|
|
vshape.SetSize(dof,spaceDim);
|
|
vec.SetSize(spaceDim);
|
|
|
|
elvect.SetSize(dof);
|
|
elvect = 0.0;
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
// int intorder = 2*el.GetOrder() - 1; // ok for O(h^{k+1}) conv. in L2
|
|
int intorder = 2*el.GetOrder();
|
|
ir = &IntRules.Get(el.GetGeomType(), intorder);
|
|
}
|
|
|
|
for (int i = 0; i < ir->GetNPoints(); i++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(i);
|
|
|
|
Tr.SetIntPoint (&ip);
|
|
el.CalcVShape(Tr, vshape);
|
|
|
|
QF.Eval (vec, Tr, ip);
|
|
vec *= ip.weight * Tr.Weight();
|
|
|
|
vshape.AddMult (vec, elvect);
|
|
}
|
|
}
|
|
|
|
void VectorFEDomainLFIntegrator::AssembleDeltaElementVect(
|
|
const FiniteElement &fe, ElementTransformation &Trans, Vector &elvect)
|
|
{
|
|
MFEM_ASSERT(vec_delta != NULL, "coefficient must be VectorDeltaCoefficient");
|
|
int dof = fe.GetDof();
|
|
int spaceDim = Trans.GetSpaceDim();
|
|
|
|
vshape.SetSize(dof, spaceDim);
|
|
fe.CalcPhysVShape(Trans, vshape);
|
|
|
|
vec_delta->EvalDelta(vec, Trans, Trans.GetIntPoint());
|
|
|
|
elvect.SetSize(dof);
|
|
vshape.Mult(vec, elvect);
|
|
}
|
|
|
|
void VectorBoundaryFluxLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
|
{
|
|
int dim = el.GetDim()+1;
|
|
int dof = el.GetDof();
|
|
|
|
shape.SetSize (dof);
|
|
nor.SetSize (dim);
|
|
elvect.SetSize (dim*dof);
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
ir = &IntRules.Get(el.GetGeomType(), el.GetOrder() + 1);
|
|
}
|
|
|
|
elvect = 0.0;
|
|
for (int i = 0; i < ir->GetNPoints(); i++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(i);
|
|
Tr.SetIntPoint (&ip);
|
|
CalcOrtho(Tr.Jacobian(), nor);
|
|
el.CalcShape (ip, shape);
|
|
nor *= Sign * ip.weight * F -> Eval (Tr, ip);
|
|
for (int j = 0; j < dof; j++)
|
|
for (int k = 0; k < dim; k++)
|
|
{
|
|
elvect(dof*k+j) += nor(k) * shape(j);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void VectorFEBoundaryFluxLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
|
{
|
|
int dof = el.GetDof();
|
|
|
|
shape.SetSize(dof);
|
|
elvect.SetSize(dof);
|
|
elvect = 0.0;
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
int intorder = oa * el.GetOrder() + ob; // <----------
|
|
ir = &IntRules.Get(el.GetGeomType(), intorder);
|
|
}
|
|
|
|
for (int i = 0; i < ir->GetNPoints(); i++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(i);
|
|
el.CalcShape(ip, shape);
|
|
|
|
double val = ip.weight;
|
|
if (F)
|
|
{
|
|
Tr.SetIntPoint (&ip);
|
|
val *= F->Eval(Tr, ip);
|
|
}
|
|
|
|
elvect.Add(val, shape);
|
|
}
|
|
}
|
|
|
|
|
|
void VectorFEBoundaryTangentLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
|
{
|
|
int dof = el.GetDof();
|
|
DenseMatrix vshape(dof, 2);
|
|
Vector f_loc(3);
|
|
Vector f_hat(2);
|
|
|
|
elvect.SetSize(dof);
|
|
elvect = 0.0;
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
int intorder = oa * el.GetOrder() + ob; // <----------
|
|
ir = &IntRules.Get(el.GetGeomType(), intorder);
|
|
}
|
|
|
|
for (int i = 0; i < ir->GetNPoints(); i++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(i);
|
|
|
|
Tr.SetIntPoint(&ip);
|
|
f.Eval(f_loc, Tr, ip);
|
|
Tr.Jacobian().MultTranspose(f_loc, f_hat);
|
|
el.CalcVShape(ip, vshape);
|
|
|
|
Swap<double>(f_hat(0), f_hat(1));
|
|
f_hat(0) = -f_hat(0);
|
|
f_hat *= ip.weight;
|
|
vshape.AddMult(f_hat, elvect);
|
|
}
|
|
}
|
|
|
|
|
|
void BoundaryFlowIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
|
{
|
|
mfem_error("BoundaryFlowIntegrator::AssembleRHSElementVect\n"
|
|
" is not implemented as boundary integrator!\n"
|
|
" Use LinearForm::AddBdrFaceIntegrator instead of\n"
|
|
" LinearForm::AddBoundaryIntegrator.");
|
|
}
|
|
|
|
void BoundaryFlowIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, FaceElementTransformations &Tr, Vector &elvect)
|
|
{
|
|
int dim, ndof, order;
|
|
double un, w, vu_data[3], nor_data[3];
|
|
|
|
dim = el.GetDim();
|
|
ndof = el.GetDof();
|
|
Vector vu(vu_data, dim), nor(nor_data, dim);
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
// Assuming order(u)==order(mesh)
|
|
order = Tr.Elem1->OrderW() + 2*el.GetOrder();
|
|
if (el.Space() == FunctionSpace::Pk)
|
|
{
|
|
order++;
|
|
}
|
|
ir = &IntRules.Get(Tr.GetGeometryType(), order);
|
|
}
|
|
|
|
shape.SetSize(ndof);
|
|
elvect.SetSize(ndof);
|
|
elvect = 0.0;
|
|
|
|
for (int p = 0; p < ir->GetNPoints(); p++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(p);
|
|
IntegrationPoint eip;
|
|
Tr.Loc1.Transform(ip, eip);
|
|
el.CalcShape(eip, shape);
|
|
|
|
Tr.SetIntPoint(&ip);
|
|
|
|
// Use Tr.Elem1 transformation for u so that it matches the coefficient
|
|
// used with the ConvectionIntegrator and/or the DGTraceIntegrator.
|
|
u->Eval(vu, *Tr.Elem1, eip);
|
|
|
|
if (dim == 1)
|
|
{
|
|
nor(0) = 2*eip.x - 1.0;
|
|
}
|
|
else
|
|
{
|
|
CalcOrtho(Tr.Jacobian(), nor);
|
|
}
|
|
|
|
un = vu * nor;
|
|
w = 0.5*alpha*un - beta*fabs(un);
|
|
w *= ip.weight*f->Eval(Tr, ip);
|
|
elvect.Add(w, shape);
|
|
}
|
|
}
|
|
|
|
|
|
void DGDirichletLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
|
{
|
|
mfem_error("DGDirichletLFIntegrator::AssembleRHSElementVect");
|
|
}
|
|
|
|
void DGDirichletLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, FaceElementTransformations &Tr, Vector &elvect)
|
|
{
|
|
int dim, ndof;
|
|
bool kappa_is_nonzero = (kappa != 0.);
|
|
double w;
|
|
|
|
dim = el.GetDim();
|
|
ndof = el.GetDof();
|
|
|
|
nor.SetSize(dim);
|
|
nh.SetSize(dim);
|
|
ni.SetSize(dim);
|
|
adjJ.SetSize(dim);
|
|
if (MQ)
|
|
{
|
|
mq.SetSize(dim);
|
|
}
|
|
|
|
shape.SetSize(ndof);
|
|
dshape.SetSize(ndof, dim);
|
|
dshape_dn.SetSize(ndof);
|
|
|
|
elvect.SetSize(ndof);
|
|
elvect = 0.0;
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
// a simple choice for the integration order; is this OK?
|
|
int order = 2*el.GetOrder();
|
|
ir = &IntRules.Get(Tr.GetGeometryType(), order);
|
|
}
|
|
|
|
for (int p = 0; p < ir->GetNPoints(); p++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(p);
|
|
IntegrationPoint eip;
|
|
|
|
Tr.Loc1.Transform(ip, eip);
|
|
Tr.SetIntPoint(&ip);
|
|
if (dim == 1)
|
|
{
|
|
nor(0) = 2*eip.x - 1.0;
|
|
}
|
|
else
|
|
{
|
|
CalcOrtho(Tr.Jacobian(), nor);
|
|
}
|
|
|
|
el.CalcShape(eip, shape);
|
|
el.CalcDShape(eip, dshape);
|
|
|
|
// compute uD through the face transformation
|
|
w = ip.weight * uD->Eval(Tr, ip) / Tr.Elem1->Weight();
|
|
if (!MQ)
|
|
{
|
|
if (Q)
|
|
{
|
|
w *= Q->Eval(Tr, ip);
|
|
}
|
|
ni.Set(w, nor);
|
|
}
|
|
else
|
|
{
|
|
nh.Set(w, nor);
|
|
MQ->Eval(mq, Tr, ip);
|
|
mq.MultTranspose(nh, ni);
|
|
}
|
|
CalcAdjugate(Tr.Elem1->Jacobian(), adjJ);
|
|
adjJ.Mult(ni, nh);
|
|
|
|
dshape.Mult(nh, dshape_dn);
|
|
elvect.Add(sigma, dshape_dn);
|
|
|
|
if (kappa_is_nonzero)
|
|
{
|
|
elvect.Add(kappa*(ni*nor), shape);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void DGElasticityDirichletLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
|
|
{
|
|
mfem_error("DGElasticityDirichletLFIntegrator::AssembleRHSElementVect");
|
|
}
|
|
|
|
void DGElasticityDirichletLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &el, FaceElementTransformations &Tr, Vector &elvect)
|
|
{
|
|
MFEM_ASSERT(Tr.Elem2No < 0, "interior boundary is not supported");
|
|
|
|
#ifdef MFEM_THREAD_SAFE
|
|
Vector shape;
|
|
DenseMatrix dshape;
|
|
DenseMatrix adjJ;
|
|
DenseMatrix dshape_ps;
|
|
Vector nor;
|
|
Vector dshape_dn;
|
|
Vector dshape_du;
|
|
Vector u_dir;
|
|
#endif
|
|
|
|
const int dim = el.GetDim();
|
|
const int ndofs = el.GetDof();
|
|
const int nvdofs = dim*ndofs;
|
|
|
|
elvect.SetSize(nvdofs);
|
|
elvect = 0.0;
|
|
|
|
adjJ.SetSize(dim);
|
|
shape.SetSize(ndofs);
|
|
dshape.SetSize(ndofs, dim);
|
|
dshape_ps.SetSize(ndofs, dim);
|
|
nor.SetSize(dim);
|
|
dshape_dn.SetSize(ndofs);
|
|
dshape_du.SetSize(ndofs);
|
|
u_dir.SetSize(dim);
|
|
|
|
const IntegrationRule *ir = IntRule;
|
|
if (ir == NULL)
|
|
{
|
|
const int order = 2*el.GetOrder(); // <-----
|
|
ir = &IntRules.Get(Tr.GetGeometryType(), order);
|
|
}
|
|
|
|
for (int pi = 0; pi < ir->GetNPoints(); ++pi)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(pi);
|
|
IntegrationPoint eip;
|
|
Tr.Loc1.Transform(ip, eip);
|
|
Tr.SetIntPoint(&ip);
|
|
|
|
// Evaluate the Dirichlet b.c. using the face transformation.
|
|
uD.Eval(u_dir, Tr, ip);
|
|
|
|
el.CalcShape(eip, shape);
|
|
el.CalcDShape(eip, dshape);
|
|
|
|
CalcAdjugate(Tr.Elem1->Jacobian(), adjJ);
|
|
Mult(dshape, adjJ, dshape_ps);
|
|
|
|
if (dim == 1)
|
|
{
|
|
nor(0) = 2*eip.x - 1.0;
|
|
}
|
|
else
|
|
{
|
|
CalcOrtho(Tr.Jacobian(), nor);
|
|
}
|
|
|
|
double wL, wM, jcoef;
|
|
{
|
|
const double w = ip.weight / Tr.Elem1->Weight();
|
|
wL = w * lambda->Eval(*Tr.Elem1, eip);
|
|
wM = w * mu->Eval(*Tr.Elem1, eip);
|
|
jcoef = kappa * (wL + 2.0*wM) * (nor*nor);
|
|
dshape_ps.Mult(nor, dshape_dn);
|
|
dshape_ps.Mult(u_dir, dshape_du);
|
|
}
|
|
|
|
// alpha < uD, (lambda div(v) I + mu (grad(v) + grad(v)^T)) . n > +
|
|
// + kappa < h^{-1} (lambda + 2 mu) uD, v >
|
|
|
|
// i = idof + ndofs * im
|
|
// v_phi(i,d) = delta(im,d) phi(idof)
|
|
// div(v_phi(i)) = dphi(idof,im)
|
|
// (grad(v_phi(i)))(k,l) = delta(im,k) dphi(idof,l)
|
|
//
|
|
// term 1:
|
|
// alpha < uD, lambda div(v_phi(i)) n >
|
|
// alpha lambda div(v_phi(i)) (uD.n) =
|
|
// alpha lambda dphi(idof,im) (uD.n) --> quadrature -->
|
|
// ip.weight/det(J1) alpha lambda (uD.nor) dshape_ps(idof,im) =
|
|
// alpha * wL * (u_dir*nor) * dshape_ps(idof,im)
|
|
// term 2:
|
|
// < alpha uD, mu grad(v_phi(i)).n > =
|
|
// alpha mu uD^T grad(v_phi(i)) n =
|
|
// alpha mu uD(k) delta(im,k) dphi(idof,l) n(l) =
|
|
// alpha mu uD(im) dphi(idof,l) n(l) --> quadrature -->
|
|
// ip.weight/det(J1) alpha mu uD(im) dshape_ps(idof,l) nor(l) =
|
|
// alpha * wM * u_dir(im) * dshape_dn(idof)
|
|
// term 3:
|
|
// < alpha uD, mu (grad(v_phi(i)))^T n > =
|
|
// alpha mu n^T grad(v_phi(i)) uD =
|
|
// alpha mu n(k) delta(im,k) dphi(idof,l) uD(l) =
|
|
// alpha mu n(im) dphi(idof,l) uD(l) --> quadrature -->
|
|
// ip.weight/det(J1) alpha mu nor(im) dshape_ps(idof,l) uD(l) =
|
|
// alpha * wM * nor(im) * dshape_du(idof)
|
|
// term j:
|
|
// < kappa h^{-1} (lambda + 2 mu) uD, v_phi(i) > =
|
|
// kappa/h (lambda + 2 mu) uD(k) v_phi(i,k) =
|
|
// kappa/h (lambda + 2 mu) uD(k) delta(im,k) phi(idof) =
|
|
// kappa/h (lambda + 2 mu) uD(im) phi(idof) --> quadrature -->
|
|
// [ 1/h = |nor|/det(J1) ]
|
|
// ip.weight/det(J1) |nor|^2 kappa (lambda + 2 mu) uD(im) phi(idof) =
|
|
// jcoef * u_dir(im) * shape(idof)
|
|
|
|
wM *= alpha;
|
|
const double t1 = alpha * wL * (u_dir*nor);
|
|
for (int im = 0, i = 0; im < dim; ++im)
|
|
{
|
|
const double t2 = wM * u_dir(im);
|
|
const double t3 = wM * nor(im);
|
|
const double tj = jcoef * u_dir(im);
|
|
for (int idof = 0; idof < ndofs; ++idof, ++i)
|
|
{
|
|
elvect(i) += (t1*dshape_ps(idof,im) + t2*dshape_dn(idof) +
|
|
t3*dshape_du(idof) + tj*shape(idof));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void VectorQuadratureLFIntegrator::AssembleRHSElementVect(
|
|
const FiniteElement &fe, ElementTransformation &Tr, Vector &elvect)
|
|
{
|
|
const IntegrationRule *ir =
|
|
&vqfc.GetQuadFunction().GetSpace()->GetElementIntRule(Tr.ElementNo);
|
|
|
|
const int nqp = ir->GetNPoints();
|
|
const int vdim = vqfc.GetVDim();
|
|
const int ndofs = fe.GetDof();
|
|
Vector shape(ndofs);
|
|
Vector temp(vdim);
|
|
elvect.SetSize(vdim * ndofs);
|
|
elvect = 0.0;
|
|
for (int q = 0; q < nqp; q++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(q);
|
|
Tr.SetIntPoint(&ip);
|
|
const double w = Tr.Weight() * ip.weight;
|
|
vqfc.Eval(temp, Tr, ip);
|
|
fe.CalcShape(ip, shape);
|
|
for (int ind = 0; ind < vdim; ind++)
|
|
{
|
|
for (int nd = 0; nd < ndofs; nd++)
|
|
{
|
|
elvect(nd + ind * ndofs) += w * shape(nd) * temp(ind);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void QuadratureLFIntegrator::AssembleRHSElementVect(const FiniteElement &fe,
|
|
ElementTransformation &Tr,
|
|
Vector &elvect)
|
|
{
|
|
const IntegrationRule *ir =
|
|
&qfc.GetQuadFunction().GetSpace()->GetElementIntRule(Tr.ElementNo);
|
|
|
|
const int nqp = ir->GetNPoints();
|
|
const int ndofs = fe.GetDof();
|
|
Vector shape(ndofs);
|
|
elvect.SetSize(ndofs);
|
|
elvect = 0.0;
|
|
for (int q = 0; q < nqp; q++)
|
|
{
|
|
const IntegrationPoint &ip = ir->IntPoint(q);
|
|
Tr.SetIntPoint (&ip);
|
|
const double w = Tr.Weight() * ip.weight;
|
|
double temp = qfc.Eval(Tr, ip);
|
|
fe.CalcShape(ip, shape);
|
|
shape *= (w * temp);
|
|
elvect += shape;
|
|
}
|
|
}
|
|
|
|
}
|