1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
25 tractionBoundaryGradient
30 \*---------------------------------------------------------------------------*/
32 #include "tractionBoundaryGradient.H"
35 //#include "plasticityModel.H"
36 #include "constitutiveModel.H"
37 #include "thermalModel.H"
40 // * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * * //
42 Foam::tmp<Foam::vectorField> Foam::tractionBoundaryGradient::traction
44 const tensorField& gradField,
45 const word& workingFieldName,
46 const word& integralFieldName,
48 const bool orthotropic,
49 const nonLinearGeometry::nonLinearType& nonLinear,
50 const bool incremental
54 tmp<vectorField> ttraction
56 new vectorField(gradField.size(), vector::zero)
58 vectorField& traction = ttraction();
60 // Orthotropic material
63 // For now, turn off orthotropic
66 "tmp<vectorField> tractionBoundaryGradient::traction\n"
68 " const tensorField& gradField,\n"
69 " const word& workingFieldName,\n"
70 " const word& integralFieldName,\n"
71 " const fvPatch& patch,\n"
72 " const bool orthotropic,\n"
73 " const nonLinearGeometry::nonLinearType& nonLinear\n"
75 ) << "tractionBoundaryGradient::traction is not written for"
76 << " orthotropic materials yet" << nl
77 << "you are probably trying to use solidContact boundaries "
78 << "with the orthotropic solver" << nl
83 // Lookup material properties from the solver
84 const fvPatchScalarField& mu =
85 patch.lookupPatchField<volScalarField, scalar>("mu");
87 const fvPatchScalarField& lambda =
88 patch.lookupPatchField<volScalarField, scalar>("lambda");
90 // only for nonlinear elastic properties
91 // if (rheology.type() == plasticityModel::typeName)
93 // const plasticityModel& plasticity =
94 // refCast<const plasticityModel>(rheology);
96 // mu = plasticity.newMu().boundaryField()[patch.index()];
97 // lambda = plasticity.newLambda().boundaryField()[patch.index()];
101 vectorField n = patch.nf();
103 // Calculate traction
104 traction = 2*mu*(n & symm(gradField)) + lambda*tr(gradField)*n;
106 // Plasticity effects
107 const constitutiveModel& rheology =
108 patch.boundaryMesh().mesh().objectRegistry::
109 lookupObject<constitutiveModel>("rheologyProperties");
111 if (rheology.plasticityActive())
114 2*mu*(n & rheology.DEpsilonP().boundaryField()[patch.index()]);
120 patch.boundaryMesh().mesh().objectRegistry::
121 foundObject<thermalModel>("thermalProperties")
124 const thermalModel& thermo =
125 patch.boundaryMesh().mesh().objectRegistry::
126 lookupObject<thermalModel>("thermalProperties");
128 const fvPatchScalarField& threeKalpha =
129 patch.lookupPatchField<volScalarField, scalar>
130 ("((threeK*rho)*alpha)");
132 // Incremental thermal contribution
135 const fvPatchScalarField& DT =
136 patch.lookupPatchField<volScalarField, scalar>("DT");
138 traction -= (n*threeKalpha*DT);
142 const fvPatchScalarField& T =
143 patch.lookupPatchField<volScalarField, scalar>("T");
145 const scalarField T0 =
146 thermo.T0()().boundaryField()[patch.index()];
148 traction -= (n*threeKalpha*(T - T0));
155 nonLinear == nonLinearGeometry::UPDATED_LAGRANGIAN
156 || nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
160 (n & (mu*(gradField & gradField.T())))
161 + 0.5*n*lambda*(gradField && gradField);
166 && nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
169 // Incremental total Lagrangian
171 const fvPatchTensorField& gradU =
172 patch.lookupPatchField<volTensorField, tensor>
174 "grad(" + integralFieldName + ")"
183 (gradU & gradField.T())
184 + (gradField & gradU.T())
190 (gradU & gradField.T())
191 + (gradField & gradU.T())
197 // Add old stress for incremental approaches
200 // add on old traction
201 const fvPatchSymmTensorField& sigma =
202 patch.lookupPatchField<volSymmTensorField, symmTensor>
207 traction += (n & sigma);
210 // Visco-elastic effects
211 if (rheology.viscoActive())
213 const fvPatchSymmTensorField& DSigmaCorr =
214 patch.lookupPatchField<volSymmTensorField, symmTensor>
219 traction += (n & DSigmaCorr);
222 // Updated Lagrangian or total Lagrangian large strain
225 nonLinear == nonLinearGeometry::UPDATED_LAGRANGIAN
226 || nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
229 tensorField F = I + gradField;
234 && nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
237 // Incremental total Lagrangian
239 const fvPatchTensorField& gradU =
240 patch.lookupPatchField<volTensorField, tensor>
242 "grad(" + integralFieldName + ")"
248 tensorField Finv = inv(F);
249 scalarField J = det(F);
251 // Rotate second Piola Kirchhoff traction to be Cauchy traction
252 traction = (traction & F)/(mag(J * Finv & n));
260 // * * * * * * * * * * * * * * * * Operators * * * * * * * * * * * * * * //
262 Foam::tmp<Foam::vectorField> Foam::tractionBoundaryGradient::snGrad
264 const vectorField& traction,
265 const scalarField& pressure,
266 const word& workingFieldName,
267 const word& integralFieldName,
268 const fvPatch& patch,
269 const bool orthotropic,
270 const nonLinearGeometry::nonLinearType& nonLinear,
271 const bool incremental
275 tmp<vectorField> tgradient(new vectorField(traction.size(), vector::zero));
276 vectorField& gradient = tgradient();
278 // Orthotropic material
281 // Get mechanical properties
282 const constitutiveModel& rheology =
283 patch.boundaryMesh().mesh().objectRegistry::
284 lookupObject<constitutiveModel>("rheologyProperties");
286 const diagTensorField K =
287 rheology.K()().boundaryField()[patch.index()];
289 const symmTensor4thOrderField C =
290 rheology.C()().boundaryField()[patch.index()];
293 vectorField n = patch.nf();
294 const diagTensorField Kinv = inv(K);
295 const fvPatchTensorField& gradField =
296 patch.lookupPatchField<volTensorField, tensor>
298 "grad(" + workingFieldName + ")"
301 // Calculate the traction to apply
302 vectorField Traction(n.size(), vector::zero);
303 tensorField sigmaExp(n.size(), tensor::zero);
305 // Total Lagrangian, small strain
309 && nonLinear == nonLinearGeometry::OFF
312 // Use total traction
313 Traction = (traction - n*pressure);
315 sigmaExp = (n*(n&(C && symm(gradField)))) - (K & gradField);
317 // Incremental total Lagrangian small strain
321 && nonLinear == nonLinearGeometry::OFF
324 const fvPatchSymmTensorField& sigma =
325 patch.lookupPatchField<volSymmTensorField, symmTensor>
330 // Increment of traction
331 Traction = (traction - n*pressure) - (n & sigma);
333 sigmaExp = (n*(n&(C && symm(gradField)))) - (K & gradField);
335 // Updated Lagrangian large strain
338 nonLinear == nonLinearGeometry::UPDATED_LAGRANGIAN
341 const fvPatchSymmTensorField& sigma =
342 patch.lookupPatchField<volSymmTensorField, symmTensor>
347 tensorField F = I + gradField;
348 tensorField Finv = inv(F);
349 scalarField J = det(F);
350 vectorField nCurrent = Finv & n;
351 nCurrent /= mag(nCurrent) + SMALL;
352 vectorField tractionCauchy = traction - nCurrent*pressure;
354 // Increment of 2nd Piola-Kirchhoff traction
355 Traction = mag(J*(Finv & n))*(tractionCauchy & Finv) - (n & sigma);
357 sigmaExp = n*(n &(C && symm(gradField))) - (K & gradField);
363 "tmp<vectorField> tractionBoundaryGradient::snGrad\n"
365 " const vectorField& traction,\n"
366 " const scalarField& pressure,\n"
367 " const word& workingFieldName,\n"
368 " const word& integralFieldName,\n"
369 " const fvPatch& patch,\n"
370 " const bool orthotropic,\n"
371 " const nonLinearGeometry::nonLinearType& nonLinear,\n"
372 " const bool incremental\n"
374 ) << "solidTractionOrtho boundary condition not suitable for "
375 << " field " << workingFieldName << " and "
376 << nonLinearGeometry::nonLinearNames_[nonLinear]
377 << abort(FatalError);
380 gradient = n & (Kinv & ( n*(Traction) - sigmaExp ));
384 // Standard isotropic solvers
386 // Lookup material properties from the solver
387 const fvPatchScalarField& mu =
388 patch.lookupPatchField<volScalarField, scalar>("mu");
390 const fvPatchScalarField& lambda =
391 patch.lookupPatchField<volScalarField, scalar>("lambda");
393 // only for nonlinear elastic properties
394 // if (rheology.type() == plasticityModel::typeName)
396 // const plasticityModel& plasticity =
397 // refCast<const plasticityModel>(rheology);
399 // mu = plasticity.newMu().boundaryField()[patch.index()];
400 // lambda = plasticity.newLambda().boundaryField()[patch.index()];
403 vectorField n = patch.nf();
405 // gradient of the field
406 const fvPatchTensorField& gradField =
407 patch.lookupPatchField<volTensorField, tensor>
409 "grad(" + workingFieldName + ")"
413 vectorField Traction(n.size(), vector::zero);
415 // Total Lagrangian, small strain
419 && nonLinear == nonLinearGeometry::OFF
422 // Use total traction
423 Traction = (traction - n*pressure);
425 // Incremental total Lagrangian small strain
429 && nonLinear == nonLinearGeometry::OFF
432 const fvPatchSymmTensorField& sigma =
433 patch.lookupPatchField<volSymmTensorField, symmTensor>
438 // Increment of traction
439 Traction = (traction - n*pressure) - (n & sigma);
443 nonLinear == nonLinearGeometry::UPDATED_LAGRANGIAN
444 || nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
447 const fvPatchSymmTensorField& sigma =
448 patch.lookupPatchField<volSymmTensorField, symmTensor>
453 tensorField F = I + gradField;
458 && nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
461 // Incremental total Lagrangian
463 const fvPatchTensorField& gradU =
464 patch.lookupPatchField<volTensorField, tensor>
466 "grad(" + integralFieldName + ")"
472 tensorField Finv = hinv(F);
473 scalarField J = det(F);
474 vectorField nCurrent = Finv & n;
475 nCurrent /= mag(nCurrent) + SMALL;
476 vectorField tractionCauchy = traction - nCurrent*pressure;
478 Traction = mag(J*(Finv & n))*(tractionCauchy & Finv);
482 // Increment of 2nd Piola-Kirchhoff traction
483 Traction -= (n & sigma);
490 "tmp<vectorField> tractionBoundaryGradient::snGrad\n"
492 " const vectorField& traction,\n"
493 " const scalarField& pressure,\n"
494 " const word& workingFieldName,\n"
495 " const word& integralFieldName,\n"
496 " const fvPatch& patch,\n"
497 " const bool orthotropic,\n"
498 " const nonLinearGeometry::nonLinearType& nonLinear,\n"
499 " const bool incremental\n"
501 ) << " field " << workingFieldName << " and "
502 << nonLinearGeometry::nonLinearNames_[nonLinear]
503 << " nonLinear are not compatible!"
504 << abort(FatalError);
508 const constitutiveModel& rheology =
509 patch.boundaryMesh().mesh().objectRegistry::
510 lookupObject<constitutiveModel>("rheologyProperties");
512 if (rheology.viscoActive())
514 const fvPatchSymmTensorField& DSigmaCorr =
515 patch.lookupPatchField<volSymmTensorField, symmTensor>
520 Traction -= (n & DSigmaCorr);
523 // Calculate the normal gradient based on the traction
527 - (n & (mu*gradField.T() - (mu + lambda)*gradField))
528 - n*lambda*tr(gradField);
530 //- Plasticity contribution
531 if (rheology.plasticityActive())
534 2*mu*(n & rheology.DEpsilonP().boundaryField()[patch.index()]);
540 patch.boundaryMesh().mesh().objectRegistry::
541 foundObject<thermalModel>("thermalProperties")
544 const thermalModel& thermo =
545 patch.boundaryMesh().mesh().objectRegistry::
546 lookupObject<thermalModel>("thermalProperties");
548 const fvPatchScalarField& threeKalpha =
549 patch.lookupPatchField<volScalarField, scalar>
551 "((threeK*rho)*alpha)"
556 const fvPatchScalarField& DT =
557 patch.lookupPatchField<volScalarField, scalar>("DT");
559 gradient += n*threeKalpha*DT;
563 const fvPatchScalarField& T =
564 patch.lookupPatchField<volScalarField, scalar>("T");
566 const scalarField T0 =
567 thermo.T0()().boundaryField()[patch.index()];
569 gradient += n*threeKalpha*(T - T0);
573 // Higher order non-linear terms
576 nonLinear == nonLinearGeometry::UPDATED_LAGRANGIAN
577 || nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
580 // no extra relaxation
582 (n & (mu*(gradField & gradField.T())))
583 // + 0.5*n*lambda*(gradField && gradField);
584 + 0.5*n*lambda*tr(gradField & gradField.T());
589 && nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
592 // gradU is const in a time step
593 const fvPatchTensorField& gradU =
594 patch.lookupPatchField<volTensorField, tensor>("grad(U)");
602 (gradField & gradU.T())
603 + (gradU & gradField.T())
609 (gradField & gradU.T())
610 + (gradU & gradField.T())
615 gradient /= (2.0*mu + lambda);
622 // ************************************************************************* //