Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit aead253

Browse files
committedOct 27, 2016
Added: Calculation of f'(alpha) by direct integration together with f(alpha)
1 parent 57fde75 commit aead253

6 files changed

+103
-13
lines changed
 

‎FractureElasticityMonol.C

+40-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ FractureElasticityMonol::FractureElasticityMonol (unsigned short int n, int ord)
2727
crtol = 0.0;
2828
use4th = ord == 4;
2929
npv = nsd + 1;
30+
eC = 2; // Assuming third vector is phase field
3031
}
3132

3233

@@ -87,9 +88,11 @@ void FractureElasticityMonol::setMode (SIM::SolutionMode mode)
8788
case SIM::INT_FORCES:
8889
iS = 2;
8990
eBc = 3;
91+
primsol.resize(1);
92+
break;
9093

9194
case SIM::RECOVERY:
92-
primsol.resize(1);
95+
primsol.resize(FractureElasticNorm::dirDer ? 2 : 1);
9396
break;
9497

9598
default:
@@ -151,6 +154,8 @@ bool FractureElasticityMonol::initElement (const std::vector<int>& MNPC,
151154
}
152155

153156
size_t nsol = 1 + eC;
157+
if (m_mode == SIM::RECOVERY && FractureElasticNorm::dirDer)
158+
nsol++;
154159
if (elmInt.vec.size() < nsol)
155160
elmInt.vec.resize(nsol);
156161

@@ -255,6 +260,26 @@ bool FractureElasticityMonol::getSolution (Vectors& eV,
255260
std::cout <<"Element displacement vector:"<< eV.front()
256261
<<"Element phase field vector:"<< eV[eC];
257262
#endif
263+
264+
if (m_mode == SIM::RECOVERY && FractureElasticNorm::dirDer)
265+
{
266+
// Extract element solution correction vectors
267+
ierr = utl::gather(MNPC,npv,mySol.back(),temp);
268+
if (ierr > 0)
269+
{
270+
std::cerr <<" *** FractureElasticityMonol::getSolution: Detected "
271+
<< ierr <<" node numbers out of range."<< std::endl;
272+
return false;
273+
}
274+
275+
eV[eC+1] = temp.getRow(npv);
276+
eV[1] = temp.expandRows(-1);
277+
#if INT_DEBUG > 2
278+
std::cout <<"Element displacement correction vector:"<< eV[1]
279+
<<"Element phase field correction vector:"<< eV[eC+1];
280+
#endif
281+
}
282+
258283
return true;
259284
}
260285

@@ -321,5 +346,19 @@ bool FractureElasticMoNorm::evalInt (LocalIntegral& elmInt,
321346
// Integrate the dissipated energy
322347
pnorm[5] += scale*fe.detJxW;
323348

349+
if (dirDer)
350+
{
351+
Vector gradCc; // Compute the gradient of the phase field correction
352+
if (!fe.dNdX.multiply(elmInt.vec[p.eC+1],gradCc,true))
353+
return false;
354+
355+
double Cc = fe.N.dot(elmInt.vec[p.eC+1]);
356+
scale = -0.5*p.Gc*d*Cc/p.smearing + p.smearing*gradC.dot(gradCc);
357+
if (C < p.crtol) scale += p.gammaInv*C*Cc;
358+
359+
// Integrate directional derivative of the dissipated energy
360+
pnorm[4] += scale*fe.detJxW;
361+
}
362+
324363
return true;
325364
}

‎FractureElasticityVoigt.C

+20-7
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,9 @@ NormBase* FractureElasticityVoigt::getNormIntegrand (AnaSol*) const
363363
}
364364

365365

366-
int FractureElasticNorm::dbgElm = 0;
366+
bool FractureElasticNorm::extEnr = true;
367+
bool FractureElasticNorm::dirDer = false;
368+
int FractureElasticNorm::dbgElm = 0;
367369

368370

369371
FractureElasticNorm::FractureElasticNorm (FractureElasticityVoigt& p)
@@ -424,11 +426,12 @@ bool FractureElasticNorm::evalInt (LocalIntegral& elmInt,
424426
// Evaluate the strain energy at this point
425427
double Phi[4];
426428
double Gc = p.getStressDegradation(fe.N,elmInt.vec);
429+
SymmTensor sigma(eps.dim());
427430
if (p.noSplit)
428431
{
429432
// Evaluate the strain energy density at this point
430-
SymmTensor sigma(eps.dim());
431-
if (!p.material->evaluate(Bmat,sigma,Phi[2],fe,X,eps,eps,3))
433+
Matrix Cmat;
434+
if (!p.material->evaluate(Cmat,sigma,Phi[2],fe,X,eps,eps,3))
432435
return false;
433436
Phi[2] *= Gc; // Isotropic scaling
434437
Phi[0] = Phi[1] = Phi[3] = 0.0;
@@ -440,14 +443,16 @@ bool FractureElasticNorm::evalInt (LocalIntegral& elmInt,
440443
if (!p.material->evaluate(lambda,mu,fe,X))
441444
return false;
442445
// Evaluate the tensile-degraded strain energy
443-
if (!p.evalStress(lambda,mu,Gc,eps,Phi,nullptr,nullptr,true,printElm))
446+
if (!p.evalStress(lambda,mu,Gc,eps,Phi,
447+
dirDer ? &sigma : nullptr,
448+
nullptr,true,printElm))
444449
return false;
445450
}
446451

447452
// Integrate the total elastic energy
448453
pnorm[0] += Phi[2]*fe.detJxW;
449454

450-
if (p.haveLoads())
455+
if (extEnr && p.haveLoads())
451456
{
452457
// Evaluate the body load
453458
Vec3 f = p.getBodyforce(X);
@@ -460,8 +465,16 @@ bool FractureElasticNorm::evalInt (LocalIntegral& elmInt,
460465
// Integrate the tensile and compressive energies
461466
pnorm[2] += Phi[0]*fe.detJxW;
462467
pnorm[3] += Phi[1]*fe.detJxW;
463-
// Integrate the bulk energy
464-
pnorm[4] += Phi[3]*fe.detJxW;
468+
if (dirDer)
469+
{
470+
// Integrate directional derivative of the elastic energy
471+
Bmat.multiply(elmInt.vec[1],eps);
472+
double Cc = fe.N.dot(elmInt.vec[p.eC+1]);
473+
pnorm[4] += (sigma.innerProd(eps) + 2.0*Phi[0]*Cc)*fe.detJxW;
474+
}
475+
else
476+
// Integrate the bulk energy
477+
pnorm[4] += Phi[3]*fe.detJxW;
465478

466479
return true;
467480
}

‎FractureElasticityVoigt.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ class FractureElasticNorm : public ElasticityNorm
9797
//! \brief Returns the name of a norm quantity.
9898
virtual std::string getName(size_t, size_t j, const char*) const;
9999

100-
static int dbgElm; //!< Element index for debug output
100+
static bool extEnr; //!< Flag for integration of external energy
101+
static bool dirDer; //!< Flag for calculation of directional derivatives
102+
static int dbgElm; //!< Element index for debug output
101103
};
102104

103105
#endif

‎QuasiStaticSIM.C

+30-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "QuasiStaticSIM.h"
1515
#include "HermiteInterpolator.h"
16+
#include "FractureElasticityVoigt.h"
1617
#include "SIMoutput.h"
1718
#include "TimeStep.h"
1819
#include "Utilities.h"
@@ -30,6 +31,7 @@
3031
QuasiStaticSIM::QuasiStaticSIM (SIMbase& sim) : NonLinSIM(sim)
3132
{
3233
numPt = numPtPos = nDump = 0;
34+
version = 1;
3335
}
3436

3537

@@ -66,6 +68,7 @@ bool QuasiStaticSIM::parse (const TiXmlElement* elem)
6668
numPt = params.size();
6769
}
6870
utl::getAttribute(child,"nDump",nDump);
71+
utl::getAttribute(child,"version",version);
6972
}
7073

7174
return this->NonLinSIM::parse(elem);
@@ -84,6 +87,10 @@ void QuasiStaticSIM::printProblem () const
8487
IFEM::cout << (i%10 ? " " : "\n\t ") << params[i];
8588
if (nDump > 0)
8689
IFEM::cout <<"\n\tDumping f(alpha) at "<< nDump <<" sampling points.";
90+
if (version == 1)
91+
IFEM::cout <<"\n\tEvaluating f'(alpha) as {F}_int * {u}_corr.";
92+
else if (version == 2)
93+
IFEM::cout <<"\n\tEvaluating f'(alpha) by direct integration.";
8794
}
8895
IFEM::cout << std::endl;
8996
}
@@ -93,8 +100,10 @@ bool QuasiStaticSIM::evalEnergyFunctional (const TimeDomain& time,
93100
const Vectors& pSol,
94101
double* fVal, double* fDer)
95102
{
96-
if (fDer)
103+
if (fDer && version == 1)
97104
{
105+
// Integrate f'(alpha) as the dot-product between internal force vector
106+
// and the solution correction vector
98107
if (!model.setMode(SIM::INT_FORCES))
99108
return false;
100109

@@ -107,16 +116,23 @@ bool QuasiStaticSIM::evalEnergyFunctional (const TimeDomain& time,
107116
*fDer = -residual.dot(linsol);
108117
}
109118

110-
if (fVal)
119+
if (fVal || version == 2)
111120
{
121+
FractureElasticNorm::dirDer = version == 2;
122+
112123
if (!model.setMode(SIM::RECOVERY))
113124
return false;
114125

115126
Vectors gNorm;
116127
if (!model.solutionNorms(time,pSol,gNorm))
117128
return false;
118129

119-
*fVal = gNorm.front()(1) + gNorm.front()(6);
130+
if (fVal)
131+
*fVal = gNorm.front()(1) + gNorm.front()(6);
132+
if (fDer && version == 2)
133+
*fDer = gNorm.front()(5); // f'(alpha) is integrated by the norm class
134+
135+
FractureElasticNorm::dirDer = false;
120136
}
121137

122138
return true;
@@ -129,8 +145,11 @@ bool QuasiStaticSIM::lineSearch (TimeStep& param)
129145
if (numPtPos < 2)
130146
return true; // No line search
131147

148+
FractureElasticNorm::extEnr = false; // Disable external energy calculation,
149+
// since it uses a path integral valid at the converged configuration only
150+
132151
// Make a temporary copy of the primary solution
133-
Vectors tmpSol(1,solution.front());
152+
Vectors tmpSol(version == 2 ? 2 : 1, solution.front());
134153
Vector& solVec = tmpSol.front();
135154
double curr, prev;
136155

@@ -148,7 +167,13 @@ bool QuasiStaticSIM::lineSearch (TimeStep& param)
148167
std::cout <<"\tLine search? curr: "<< curr <<" prev: "<< prev << std::endl;
149168
#endif
150169
if (curr < prev)
170+
{
171+
FractureElasticNorm::extEnr = true; // Enable external energy calculation
151172
return true; // No line search needed in this iteration
173+
}
174+
175+
if (version == 2) // Store the solution correction in tmpSol
176+
tmpSol.back() = linsol;
152177

153178
// Evaluate f'(alpha) at alpha=0.0
154179
if (!this->evalEnergyFunctional(param.time,tmpSol,nullptr,&curr))
@@ -171,6 +196,7 @@ bool QuasiStaticSIM::lineSearch (TimeStep& param)
171196
if (!this->evalEnergyFunctional(param.time,tmpSol,&values[i],&derivs[i]))
172197
return false;
173198
}
199+
FractureElasticNorm::extEnr = true; // Enable external energy calculation
174200

175201
#if SP_DEBUG > 1
176202
std::cout <<"\nParameters:\n";

‎QuasiStaticSIM.h

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class QuasiStaticSIM : public NonLinSIM
5252
size_t numPt; // Total number of alpha-values
5353
size_t numPtPos; // Number of non-negative alpha-values
5454
size_t nDump; // Number of grid-points to dump f(alpha) to file for
55+
int version; // Algorithm version, for internal testing
5556
};
5657

5758
#endif

‎SIMDynElasticity.h

+9
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,15 @@ class SIMDynElasticity : public SIMElasticity<Dim>
283283
return fel ? fel->getCrackPressure() != 0.0 : false;
284284
}
285285

286+
//! \brief Computes (possibly problem-dependent) external energy contribution.
287+
virtual double externalEnergy(const Vectors& psol) const
288+
{
289+
if (FractureElasticNorm::extEnr)
290+
return this->Dim::externalEnergy(psol);
291+
292+
return 0.0; // No external energy integration
293+
}
294+
286295
protected:
287296
//! \brief Returns the actual integrand.
288297
virtual Elasticity* getIntegrand()

0 commit comments

Comments
 (0)
Please sign in to comment.