@@ -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
3940BEGIN_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" );
4345END_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+ }
0 commit comments