Skip to content

Commit 4626206

Browse files
committed
Implemented auto-pressure stabilization for biphasic solid domains.
1 parent b49665c commit 4626206

8 files changed

Lines changed: 107 additions & 3 deletions

FEBioMix/FEBioMix.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ void FEBioMix::InitModule()
244244
REGISTER_FECORE_CLASS(FEPlotSolidStress , "solid stress" );
245245
REGISTER_FECORE_CLASS(FEPlotLocalFluidLoadSupport , "local fluid load support" );
246246
REGISTER_FECORE_CLASS(FEPlotEffectiveFrictionCoeff , "effective friction coefficient" );
247+
REGISTER_FECORE_CLASS(FEPlotPressureStabilization , "pressure stabilization");
247248

248249
//-----------------------------------------------------------------------------
249250
// Element log data

FEBioMix/FEBioMixPlot.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,3 +1573,18 @@ bool FEPlotOsmoticCoefficient::Save(FEDomain &dom, FEDataStream& a)
15731573

15741574
return true;
15751575
}
1576+
1577+
bool FEPlotPressureStabilization::Save(FEDomain& dom, FEDataStream& a)
1578+
{
1579+
FEBiphasic* pb = dynamic_cast<FEBiphasic*>(dom.GetMaterial());
1580+
if (pb == nullptr) return false;
1581+
1582+
double tau_scale = pb->m_tau;
1583+
1584+
writeAverageElementValue<double>(dom, a, [=](const FEMaterialPoint& mp) {
1585+
const FEBiphasicMaterialPoint* bp = mp.ExtractData<FEBiphasicMaterialPoint>();
1586+
return (bp ? tau_scale * bp->m_tau : 0.0);
1587+
});
1588+
1589+
return true;
1590+
}

FEBioMix/FEBioMixPlot.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,14 @@ class FEPlotOsmoticCoefficient : public FEPlotDomainData
334334
bool Save(FEDomain& dom, FEDataStream& a);
335335
};
336336

337+
//! pressure stabilization factor tau
338+
class FEPlotPressureStabilization : public FEPlotDomainData
339+
{
340+
public:
341+
FEPlotPressureStabilization(FEModel* pfem) : FEPlotDomainData(pfem, PLT_FLOAT, FMT_ITEM) {}
342+
bool Save(FEDomain& dom, FEDataStream& a);
343+
};
344+
337345
//=============================================================================
338346
// S U R F A C E D A T A
339347
//=============================================================================

FEBioMix/FEBiphasic.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ void FEBiphasicMaterialPoint::Serialize(DumpStream& ar)
6767
ar & m_p & m_gradp & m_gradpp;
6868
ar & m_w & m_pa & m_phi0 & m_phi0t & m_phi0p & m_phi0hat & m_Jp;
6969
ar & m_ss;
70+
ar & m_tau;
7071
}
7172

7273
//-----------------------------------------------------------------------------
@@ -79,6 +80,7 @@ void FEBiphasicMaterialPoint::Init()
7980
m_phi0hat = 0;
8081
m_Jp = 1;
8182
m_ss.zero();
83+
m_tau = 1.0;
8284

8385
FEMaterialPointData::Init();
8486
}

FEBioMix/FEBiphasic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class FEBIOMIX_API FEBiphasicMaterialPoint : public FEMaterialPointData
7070
double m_phi0hat; //!< referential solid volume fraction supply at current time
7171
double m_Jp; //!< determinant of solid deformation gradient at previous time
7272
mat3ds m_ss; //!< solid (elastic or effective) stress
73+
double m_tau; //!< characteristic time constant for stabilization
7374
};
7475

7576
//-----------------------------------------------------------------------------

FEBioMix/FEBiphasicShellDomain.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ bool FEBiphasicShellDomain::ElementBiphasicStiffness(FEShellElement& el, matrix&
512512
int neln = el.Nodes();
513513

514514
double dt = GetFEModel()->GetTime().timeIncrement;
515-
double tau = m_pMat->m_tau;
515+
double tau_scale = m_pMat->m_tau;
516516

517517
vector<vec3d> gradMu(neln), gradMd(neln);
518518
vector<double> Mu(neln), Md(neln);
@@ -532,6 +532,8 @@ bool FEBiphasicShellDomain::ElementBiphasicStiffness(FEShellElement& el, matrix&
532532
FEMaterialPoint& mp = *el.GetMaterialPoint(n);
533533
FEElasticMaterialPoint& ept = *(mp.ExtractData<FEElasticMaterialPoint >());
534534
FEBiphasicMaterialPoint& pt = *(mp.ExtractData<FEBiphasicMaterialPoint>());
535+
536+
double tau = pt.m_tau * tau_scale;
535537

536538
// calculate the jacobian
537539
detJt = detJ(el, n);

FEBioMix/FEBiphasicSolidDomain.cpp

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,13 @@ SOFTWARE.*/
3535
#include <FEBioMech/FEBioMech.h>
3636
#include <FECore/FELinearSystem.h>
3737
#include "FEBioMix.h"
38+
#include <FECore/FEEdgeList.h>
3839

3940
BEGIN_FECORE_CLASS(FEBiphasicSolidDomain, FESolidDomain)
4041
ADD_PARAMETER(m_secant_stress, "secant_stress");
4142
ADD_PARAMETER(m_secant_tangent, "secant_tangent");
4243
ADD_PARAMETER(m_secant_perm_tangent, "secant_permeability_tangent");
44+
ADD_PARAMETER(m_auto_pressure_stab, "auto_pressure_stabilization");
4345
END_FECORE_CLASS();
4446

4547
//-----------------------------------------------------------------------------
@@ -49,6 +51,7 @@ FEBiphasicSolidDomain::FEBiphasicSolidDomain(FEModel* pfem) : FESolidDomain(pfem
4951
m_secant_stress = false;
5052
m_secant_tangent = false;
5153
m_secant_perm_tangent = false;
54+
m_auto_pressure_stab = false;
5255

5356
if (pfem)
5457
{
@@ -154,6 +157,15 @@ bool FEBiphasicSolidDomain::Init()
154157

155158
// allocate nodal pressures
156159
m_nodePressure.resize(Nodes(), 0.0);
160+
161+
if (m_auto_pressure_stab)
162+
{
163+
if (!CalcAutoPressureStabilization())
164+
{
165+
feLogError("Failed to calculate automatic pressure stabilization factor.");
166+
return false;
167+
}
168+
}
157169

158170
return true;
159171
}
@@ -600,7 +612,7 @@ bool FEBiphasicSolidDomain::ElementBiphasicStiffness(FESolidElement& el, matrix&
600612
double* gw = el.GaussWeights();
601613

602614
double dt = GetFEModel()->GetTime().timeIncrement;
603-
double tau = m_pMat->m_tau;
615+
double tau_scale = m_pMat->m_tau;
604616

605617
// zero stiffness matrix
606618
ke.zero();
@@ -611,6 +623,8 @@ bool FEBiphasicSolidDomain::ElementBiphasicStiffness(FESolidElement& el, matrix&
611623
FEMaterialPoint& mp = *el.GetMaterialPoint(n);
612624
FEElasticMaterialPoint& ept = *(mp.ExtractData<FEElasticMaterialPoint >());
613625
FEBiphasicMaterialPoint& pt = *(mp.ExtractData<FEBiphasicMaterialPoint>());
626+
627+
double tau = pt.m_tau * tau_scale;
614628

615629
// calculate jacobian
616630
double detJ = invjact(el, Ji, n);
@@ -1158,7 +1172,7 @@ vec3d FEBiphasicSolidDomain::FluidFlux(FEMaterialPoint& mp)
11581172

11591173
vec3d w = -(kt*gradp);
11601174

1161-
double tau = m_pMat->m_tau;
1175+
double tau = ppt.m_tau * m_pMat->m_tau;
11621176
if (tau > 0) {
11631177
double dt = GetFEModel()->GetTime().timeIncrement;
11641178
w -= kt*(gradp - ppt.m_gradpp)*(tau/dt);
@@ -1250,3 +1264,60 @@ void FEBiphasicSolidDomain::GetNodalPressures(vector<double>& data)
12501264
data[NodeIndex(i)] = m_nodePressure[i];
12511265
}
12521266
}
1267+
1268+
bool FEBiphasicSolidDomain::CalcAutoPressureStabilization()
1269+
{
1270+
// make sure that the biphasic tau parameter is not zero
1271+
if (m_pMat->m_tau == 0.0)
1272+
{
1273+
feLogError("When using automatic pressure stabilization, the biphasic tau parameter must be non-zero.");
1274+
return false;
1275+
}
1276+
1277+
FEEdgeList EL;
1278+
if (!EL.Create(this)) return false;
1279+
1280+
FEElementEdgeList EEL;
1281+
if (!EEL.Create(*this, EL)) return false;
1282+
1283+
FEMesh& mesh = *GetMesh();
1284+
1285+
for (int i = 0; i < Elements(); ++i)
1286+
{
1287+
FESolidElement& el = Element(i);
1288+
1289+
// get the largest edge length
1290+
const std::vector<int>& edges = EEL.EdgeList(i);
1291+
vec3d e0;
1292+
for (int j=0; j<edges.size(); ++j)
1293+
{
1294+
int edge = edges[j];
1295+
vec3d p0 = mesh.Node(EL.Edge(edge).node[0]).m_rt;
1296+
vec3d p1 = mesh.Node(EL.Edge(edge).node[1]).m_rt;
1297+
vec3d d = p1 - p0;
1298+
if (j == 0 || d.norm() > e0.norm()) e0 = d;
1299+
}
1300+
double he = e0.unit();
1301+
1302+
int nint = el.GaussPoints();
1303+
for (int n=0; n<nint; ++n)
1304+
{
1305+
FEMaterialPoint& mp = *el.GetMaterialPoint(n);
1306+
FEBiphasicMaterialPoint* bpt = (mp.ExtractData<FEBiphasicMaterialPoint>());
1307+
if (bpt == nullptr) return false;
1308+
1309+
// get the tangent stiffness
1310+
tens4dmm C = m_pMat->Tangent(mp);
1311+
double Ha = e0 * (vdotTdotv(e0, C, e0) * e0);
1312+
1313+
// get the permeability tensor
1314+
mat3ds K = m_pMat->Permeability(mp);
1315+
double k = e0 * (K * e0);
1316+
1317+
double tau = he * he / (4 * Ha * k);
1318+
1319+
bpt->m_tau = tau;
1320+
}
1321+
}
1322+
return true;
1323+
}

FEBioMix/FEBiphasicSolidDomain.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,14 @@ class FEBIOMIX_API FEBiphasicSolidDomain : public FESolidDomain, public FEBiphas
135135
// This function updates the m_nodePressure variable
136136
void UpdateNodalPressures();
137137

138+
// Calculate the automatic pressure stabilization factor
139+
bool CalcAutoPressureStabilization();
140+
138141
protected:
139142
bool m_secant_stress; //!< use secant approximation to stress
140143
bool m_secant_tangent; //!< flag for using secant tangent
141144
bool m_secant_perm_tangent; //!< flag for using secant tangent on permeability
145+
bool m_auto_pressure_stab; //!< flag for automatic pressure stabilization
142146

143147
protected:
144148
int m_varU, m_varP; // displacement, pressure field indices

0 commit comments

Comments
 (0)