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/>.
24 \*---------------------------------------------------------------------------*/
26 #include "multiMaterialCohesiveLaw.H"
27 #include "addToRunTimeSelectionTable.H"
28 #include "zeroGradientFvPatchFields.H"
30 #include "crackerFvMesh.H"
31 #include "multiMaterial.H"
32 #include "constitutiveModel.H"
33 #include "cohesiveFvPatch.H"
34 #include "cohesiveLaw.H"
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 defineTypeNameAndDebug(multiMaterialCohesiveLaw, 0);
41 addToRunTimeSelectionTable
44 multiMaterialCohesiveLaw,
50 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52 Foam::tmp<Foam::scalarField> Foam::multiMaterialCohesiveLaw::indicator
57 const scalarField& mat = materials_.internalField();
59 tmp<scalarField> tresult(new scalarField(mat.size(), 0.0));
60 scalarField& result = tresult();
64 if (mat[matI] > i - SMALL && mat[matI] < i + 1 - SMALL)
74 Foam::scalar Foam::multiMaterialCohesiveLaw::indicator
80 const scalar mat = materials_.internalField()[cellID];
83 if (mat > index - SMALL && mat < index + 1 - SMALL)
91 Foam::scalar Foam::multiMaterialCohesiveLaw::interfaceID
97 word mat1name = (*this)[mat1].name();
98 word mat2name = (*this)[mat2].name();
100 word interfaceName("interface_"+mat1name+"_"+mat2name);
101 label interfaceLawID = -1;
102 forAll(interfaceCohesiveLaws_, lawI)
104 if (interfaceCohesiveLaws_[lawI].name() == interfaceName)
106 interfaceLawID = lawI;
110 if (interfaceLawID == -1)
113 interfaceName = word("interface_"+mat2name+"_"+mat1name);
114 forAll(interfaceCohesiveLaws_, lawI)
116 if (interfaceCohesiveLaws_[lawI].name() == interfaceName)
118 interfaceLawID = lawI;
122 if (interfaceLawID == -1)
125 << "Cannot find cohesive interfaceLaw "
126 << word("interface_"+mat1name+"_"+mat2name) << " or "
127 << interfaceName << nl
128 << "One of these should be defined!"
133 return interfaceLawID;
135 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
137 // Construct from dictionary
138 Foam::multiMaterialCohesiveLaw::multiMaterialCohesiveLaw
141 const volSymmTensorField& sigma,
142 const dictionary& dict
145 cohesiveLaw(name, sigma, dict),
146 PtrList<cohesiveLaw>(),
149 sigma.mesh().objectRegistry::lookupObject<volScalarField>("materials")
155 // mesh().time().timeName(),
157 // IOobject::MUST_READ,
158 // IOobject::AUTO_WRITE
162 interfaceCohesiveLaws_() //,
168 // mesh().time().timeName(),
170 // IOobject::NO_READ,
171 // IOobject::NO_WRITE
174 // dimensionedScalar("zero", dimless, 0.0)
177 PtrList<cohesiveLaw>& laws = *this;
179 PtrList<entry> lawEntries(dict.lookup("laws"));
180 laws.setSize(lawEntries.size());
189 lawEntries[lawI].keyword(),
191 lawEntries[lawI].dict()
198 min(materials_).value() < 0
199 || max(materials_).value() > laws.size() + SMALL
204 "multiMaterialCohesiveLaw::multiMaterialCohesiveLaw\n"
206 " const word& name,\n"
207 " const volSymmTensorField& sigma,\n"
208 " const dictionary& dict\n"
210 ) << "Invalid definition of material indicator field. "
211 << "Number of materials: " << laws.size()
212 << " max index: " << max(materials_)
213 << ". Should be " << laws.size() - 1
214 << abort(FatalError);
217 // cohesive laws must be the same size as rheology laws
218 const constitutiveModel& conModel =
219 mesh().objectRegistry::lookupObject<constitutiveModel>
220 ("rheologyProperties");
221 if (conModel.law().type() == "multiMaterial")
223 const multiMaterial& mulMatLaw =
224 refCast<const multiMaterial>(conModel.law());
226 if (laws.size() != mulMatLaw.size())
229 << "There should be the same number of cohesive laws "
230 << "as rheology laws" << nl
231 << "Currently there are " << mulMatLaw.size()
233 << "and " << laws.size() << " cohesive laws!"
238 // set interfaceCohesiveLaws_
239 PtrList<entry> interfaceLawEntries(dict.lookup("interfaceLaws"));
240 // if (interfaceLawEntries.size() != int(laws.size()*(laws.size()-1)/2))
241 if ( mag(interfaceLawEntries.size() - (laws.size()*(laws.size()-1)/2))
244 // number of interfaces is a trianular number of number of materials
247 << "There are " << interfaceLawEntries.size()
248 << " interface cohesive"
249 << " laws defined, but there should be "
250 << (laws.size()*(laws.size()-1)/2)
252 << "as there are " << laws.size()
253 << " materials in cohesive laws" << nl
256 interfaceCohesiveLaws_.setSize(interfaceLawEntries.size());
257 forAll (interfaceCohesiveLaws_, lawI)
259 interfaceCohesiveLaws_.set
264 interfaceLawEntries[lawI].keyword(),
266 interfaceLawEntries[lawI].dict()
273 // materialsSurf_ = fvc::interpolate(materials_);
274 // forAll(mesh().boundary(), patchi)
276 // materialsSurf_.boundaryField()[patchi] =
277 // materials_.boundaryField()[patchi].patchInternalField();
279 // // Fix interface values
280 // const labelList owner = mesh().owner();
281 // const labelList neighbour = mesh().neighbour();
282 // forAll (materialsSurf_.internalField(), faceI)
284 // // round value to integer and check difference
285 // // if it is small then the face is not on a multi-material
287 // scalar matIDscalar = materialsSurf_.internalField()[faceI];
288 // label matID = int(matIDscalar);
289 // if (mag(matIDscalar - matID) > SMALL)
291 // // find which interface it is on
292 // const label own = owner[faceI];
293 // const label nei = neighbour[faceI];
295 // materialsSurf_.internalField()[faceI] =
296 // interfaceID(materials_[own], materials_[nei]) + laws.size();
301 // processor boundaries are meant to hold the patchNeighbourField
302 // but the proc boundaries are interpolated by decomposePar
303 // so we must correct them. Now the proc boundaries hold the
304 // patchNiehgbourField
305 //materials_.correctBoundaryConditions(); // done by rheologyLaw
309 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
311 Foam::multiMaterialCohesiveLaw::~multiMaterialCohesiveLaw()
315 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
317 Foam::tmp<Foam::volScalarField>
318 Foam::multiMaterialCohesiveLaw::materials() const
323 Foam::tmp<Foam::surfaceScalarField>
324 Foam::multiMaterialCohesiveLaw::sigmaMax() const
326 tmp<surfaceScalarField> tresult
328 new surfaceScalarField
333 mesh().time().timeName(),
339 dimensionedScalar("zero", dimForce/dimArea, 0)
342 surfaceScalarField& result = tresult();
344 // Accumulate data for all fields
345 const PtrList<cohesiveLaw>& laws = *this;
351 mesh().time().timeName(),
357 dimensionedScalar("zero", dimless, 0),
358 zeroGradientFvPatchScalarField::typeName
362 // interface fields will not be correct but we fix them after
363 indic.internalField() = indicator(lawI)();
364 surfaceScalarField indicatorSurf = fvc::interpolate(indic);
365 // fix boundary fields
366 forAll(mesh().boundary(), patchi)
368 indicatorSurf.boundaryField()[patchi] =
369 indic.boundaryField()[patchi].patchInternalField();
371 result += indicatorSurf*laws[lawI].sigmaMax()();
376 // forAll surfaces check if surface is a material interface
377 // material indicator should read non integer
378 // Get the two materials it is an interface of
379 // Look up value of sigmaMaxf in dictionary
380 // Overwrite existing value on surface with new value
382 const labelList& owner = mesh().owner();
383 const labelList& neighbour = mesh().neighbour();
385 forAll(result.internalField(), faceI)
387 label ownerMat = label(materials_[owner[faceI]]);
388 label neighbourMat = label(materials_[neighbour[faceI]]);
390 if (ownerMat != neighbourMat)
392 result.internalField()[faceI] = interfaceSigmaMax(ownerMat, neighbourMat);
396 forAll(mesh().boundary(), patchI)
399 if (mesh().boundary()[patchI].type() == cohesiveFvPatch::typeName)
401 const crackerFvMesh& crackerMesh = refCast<const crackerFvMesh>(mesh());
402 // we must use owner values
403 scalarField localPatchMaterials =
404 materials_.boundaryField()[patchI].patchInternalField();
405 scalarField globalPatchMaterials =
406 crackerMesh.globalCrackField(localPatchMaterials);
407 // crackerMesh.globalCrackField(materials_.boundaryField()[patchI]);
408 const labelList& gcfa = crackerMesh.globalCrackFaceAddressing();
409 label globalIndex = crackerMesh.localCrackStart();
411 forAll(mesh().boundaryMesh()[patchI], facei)
413 label ownerMat = label(globalPatchMaterials[globalIndex]);
414 label neighbourMat = label(globalPatchMaterials[gcfa[globalIndex]]);
416 if (ownerMat != neighbourMat)
418 result.boundaryField()[patchI][facei] =
419 interfaceSigmaMax(ownerMat, neighbourMat);
426 else if (mesh().boundary()[patchI].coupled())
428 const scalarField ownerMatField =
429 materials_.boundaryField()[patchI].patchInternalField();
430 const scalarField neighbourMatField =
431 materials_.boundaryField()[patchI].patchNeighbourField();
432 //const labelList& faceCells = mesh().boundary()[patchI].faceCells();
434 forAll(mesh().boundaryMesh()[patchI], facei)
436 label ownerMat = label(ownerMatField[facei]);
437 label neighbourMat = label(neighbourMatField[facei]);
439 if (ownerMat != neighbourMat)
441 // result.boundaryField()[patchI][facei] = sigmaMax();
442 result.boundaryField()[patchI][facei] =
443 interfaceSigmaMax(ownerMat, neighbourMat);
453 Foam::tmp<Foam::surfaceScalarField>
454 Foam::multiMaterialCohesiveLaw::tauMax() const
456 tmp<surfaceScalarField> tresult
458 new surfaceScalarField
463 mesh().time().timeName(),
469 dimensionedScalar("zero", dimForce/dimArea, 0)
472 surfaceScalarField& result = tresult();
474 const PtrList<cohesiveLaw>& laws = *this;
480 mesh().time().timeName(),
486 dimensionedScalar("zero", dimless, 0),
487 zeroGradientFvPatchScalarField::typeName
491 // interface fields will not be correct but we fix them after
492 indic.internalField() = indicator(lawI)();
493 surfaceScalarField indicatorSurf = fvc::interpolate(indic);
494 // fix boundary fields
495 forAll(mesh().boundary(), patchi)
497 indicatorSurf.boundaryField()[patchi] =
498 indic.boundaryField()[patchi].patchInternalField();
500 result += indicatorSurf*laws[lawI].tauMax()();
503 // forAll surfaces check if surface is a material interface
504 // material indicator should read non integer
505 // Get the two materials it is an interface of
506 // Look up value of tauMaxf in dictionary
507 // Overwrite existing value on surface with new value
509 const labelList& owner = mesh().owner();
510 const labelList& neighbour = mesh().neighbour();
512 forAll(result.internalField(), faceI)
514 label ownerMat = label(materials_[owner[faceI]]);
515 label neighbourMat = label(materials_[neighbour[faceI]]);
517 if (ownerMat != neighbourMat)
519 result.internalField()[faceI] = interfaceTauMax(ownerMat, neighbourMat);
523 forAll(mesh().boundary(), patchI)
526 if (mesh().boundary()[patchI].type() == cohesiveFvPatch::typeName)
528 //label size = (mesh().boundary()[patchI].size())/2;
529 const crackerFvMesh& crackerMesh = refCast<const crackerFvMesh>(mesh());
530 // we must use owner values
531 scalarField localPatchMaterials =
532 materials_.boundaryField()[patchI].patchInternalField();
533 scalarField globalPatchMaterials =
534 crackerMesh.globalCrackField(localPatchMaterials);
535 // crackerMesh.globalCrackField(materials_.boundaryField()[patchI]);
536 const labelList& gcfa = crackerMesh.globalCrackFaceAddressing();
537 label globalIndex = crackerMesh.localCrackStart();
539 forAll(mesh().boundaryMesh()[patchI], facei)
541 label ownerMat = label(globalPatchMaterials[globalIndex]);
542 label neighbourMat = label(globalPatchMaterials[gcfa[globalIndex]]);
544 if (ownerMat != neighbourMat)
546 result.boundaryField()[patchI][facei] =
547 interfaceTauMax(ownerMat, neighbourMat);
554 else if (mesh().boundary()[patchI].coupled())
556 const scalarField ownerMatField =
557 materials_.boundaryField()[patchI].patchInternalField();
558 const scalarField neighbourMatField =
559 materials_.boundaryField()[patchI].patchNeighbourField();
560 //const labelList& faceCells = mesh().boundary()[patchI].faceCells();
562 forAll(mesh().boundaryMesh()[patchI], facei)
564 label ownerMat = label(ownerMatField[facei]);
565 label neighbourMat = label(neighbourMatField[facei]);
567 if (ownerMat != neighbourMat)
569 result.boundaryField()[patchI][facei] =
570 interfaceTauMax(ownerMat, neighbourMat);
579 Foam::tmp<Foam::surfaceScalarField> Foam::multiMaterialCohesiveLaw::GIc() const
581 tmp<surfaceScalarField> tresult
583 new surfaceScalarField
588 mesh().time().timeName(),
594 dimensionedScalar("zero", dimForce*dimLength/dimArea, 0)
597 surfaceScalarField& result = tresult();
599 const PtrList<cohesiveLaw>& laws = *this;
605 mesh().time().timeName(),
611 dimensionedScalar("zero", dimless, 0),
612 zeroGradientFvPatchScalarField::typeName
616 // interface fields will not be correct but we fix them after
617 indic.internalField() = indicator(lawI)();
618 surfaceScalarField indicatorSurf = fvc::interpolate(indic);
619 // fix boundary fields
620 forAll(mesh().boundary(), patchi)
622 indicatorSurf.boundaryField()[patchi] =
623 indic.boundaryField()[patchi].patchInternalField();
625 result += indicatorSurf*laws[lawI].GIc()();
628 const labelList& owner = mesh().owner();
629 const labelList& neighbour = mesh().neighbour();
631 forAll(result.internalField(), faceI)
633 label ownerMat = label(materials_[owner[faceI]]);
634 label neighbourMat = label(materials_[neighbour[faceI]]);
636 if (ownerMat != neighbourMat)
638 result.internalField()[faceI] = interfaceGIc(ownerMat, neighbourMat);
642 forAll(mesh().boundary(), patchI)
645 if (mesh().boundary()[patchI].type() == cohesiveFvPatch::typeName)
647 //label size = (mesh().boundary()[patchI].size())/2;
648 // const labelList& fCells = mesh().boundary()[patchI].faceCells();
649 scalarField localPatchMaterials =
650 materials_.boundaryField()[patchI].patchInternalField();
651 const crackerFvMesh& crackerMesh = refCast<const crackerFvMesh>(mesh());
652 scalarField globalPatchMaterials =
653 crackerMesh.globalCrackField(localPatchMaterials);
654 const labelList& gcfa = crackerMesh.globalCrackFaceAddressing();
655 label globalIndex = crackerMesh.localCrackStart();
657 forAll(mesh().boundaryMesh()[patchI], facei)
659 label ownerMat = label(globalPatchMaterials[globalIndex]);
660 label neighbourMat = label(globalPatchMaterials[gcfa[globalIndex]]);
662 if (ownerMat != neighbourMat)
664 result.boundaryField()[patchI][facei] =
665 interfaceGIc(ownerMat, neighbourMat);
670 else if (mesh().boundary()[patchI].coupled())
672 const scalarField ownerMatField =
673 materials_.boundaryField()[patchI].internalField();
674 const scalarField neighbourMatField =
675 materials_.boundaryField()[patchI].patchNeighbourField();
677 forAll(mesh().boundaryMesh()[patchI], facei)
679 label ownerMat = label(ownerMatField[facei]);
680 label neighbourMat = label(neighbourMatField[facei]);
682 if (ownerMat != neighbourMat)
684 //result.boundaryField()[patchI][facei] = iterGIc();
685 result.boundaryField()[patchI][facei] =
686 interfaceGIc(ownerMat, neighbourMat);
695 Foam::tmp<Foam::surfaceScalarField> Foam::multiMaterialCohesiveLaw::GIIc() const
697 tmp<surfaceScalarField> tresult
699 new surfaceScalarField
704 mesh().time().timeName(),
710 dimensionedScalar("zero", dimForce*dimLength/dimArea, 0)
713 surfaceScalarField& result = tresult();
715 const PtrList<cohesiveLaw>& laws = *this;
721 mesh().time().timeName(),
727 dimensionedScalar("zero", dimless, 0),
728 zeroGradientFvPatchScalarField::typeName
732 // interface fields will not be correct but we fix them after
733 indic.internalField() = indicator(lawI)();
734 surfaceScalarField indicatorSurf = fvc::interpolate(indic);
735 // fix boundary fields
736 forAll(mesh().boundary(), patchi)
738 indicatorSurf.boundaryField()[patchi] =
739 indic.boundaryField()[patchi].patchInternalField();
741 result += indicatorSurf*laws[lawI].GIIc()();
744 const labelList& owner = mesh().owner();
745 const labelList& neighbour = mesh().neighbour();
747 forAll(result.internalField(), faceI)
749 label ownerMat = label(materials_[owner[faceI]]);
750 label neighbourMat = label(materials_[neighbour[faceI]]);
752 if (ownerMat != neighbourMat)
754 result.internalField()[faceI] = interfaceGIIc(ownerMat, neighbourMat);
758 forAll(mesh().boundary(), patchI)
761 if (mesh().boundary()[patchI].type() == cohesiveFvPatch::typeName)
763 //label size = (mesh().boundary()[patchI].size())/2;
764 // const labelList& fCells = mesh().boundary()[patchI].faceCells();
765 scalarField localPatchMaterials =
766 materials_.boundaryField()[patchI].patchInternalField();
767 const crackerFvMesh& crackerMesh = refCast<const crackerFvMesh>(mesh());
768 scalarField globalPatchMaterials =
769 crackerMesh.globalCrackField(localPatchMaterials);
770 const labelList& gcfa = crackerMesh.globalCrackFaceAddressing();
771 label globalIndex = crackerMesh.localCrackStart();
773 forAll(mesh().boundaryMesh()[patchI], facei)
775 label ownerMat = label(globalPatchMaterials[globalIndex]);
776 label neighbourMat = label(globalPatchMaterials[gcfa[globalIndex]]);
778 if (ownerMat != neighbourMat)
780 result.boundaryField()[patchI][facei] =
781 interfaceGIIc(ownerMat, neighbourMat);
787 else if (mesh().boundary()[patchI].coupled())
789 const scalarField ownerMatField =
790 materials_.boundaryField()[patchI].internalField();
791 const scalarField neighbourMatField =
792 materials_.boundaryField()[patchI].patchNeighbourField();
794 forAll(mesh().boundaryMesh()[patchI], facei)
796 label ownerMat = label(ownerMatField[facei]);
797 label neighbourMat = label(neighbourMatField[facei]);
799 if (ownerMat != neighbourMat)
801 result.boundaryField()[patchI][facei] =
802 interfaceGIIc(ownerMat, neighbourMat);
812 Foam::scalar Foam::multiMaterialCohesiveLaw::interfaceSigmaMax
818 label interfaceLawID = interfaceID(mat1, mat2);
820 return interfaceCohesiveLaws_[interfaceLawID].sigmaMaxValue();
823 Foam::scalar Foam::multiMaterialCohesiveLaw::
830 label interfaceLawID = interfaceID(mat1, mat2);
832 return interfaceCohesiveLaws_[interfaceLawID].tauMaxValue();
835 Foam::scalar Foam::multiMaterialCohesiveLaw::interfaceGIc
841 label interfaceLawID = interfaceID(mat1, mat2);
843 return interfaceCohesiveLaws_[interfaceLawID].GIcValue();
846 Foam::scalar Foam::multiMaterialCohesiveLaw::interfaceGIIc
852 label interfaceLawID = interfaceID(mat1, mat2);
854 return interfaceCohesiveLaws_[interfaceLawID].GIIcValue();
858 void Foam::multiMaterialCohesiveLaw::damageTractions
867 const scalarField& globalPatchMaterials
870 // Find out which cohesive law does the face belong to
871 const crackerFvMesh& crackerMesh = refCast<const crackerFvMesh>(mesh());
872 const labelList& gcfa = crackerMesh.globalCrackFaceAddressing();
873 label ownerMat = label(globalPatchMaterials[faceID]);
874 label neighbourMat = label(globalPatchMaterials[gcfa[faceID]]);
876 if (ownerMat != neighbourMat)
878 label matID = interfaceID(ownerMat, neighbourMat);
880 // face is on multi-material interface
881 interfaceCohesiveLaws_[matID].damageTractions
882 (tN, tS, deltaN, deltaS, GI, GII, faceID, globalPatchMaterials);
886 // face is within one material
887 // call material law function
888 label matID = ownerMat;
889 (*this)[matID].damageTractions
890 (tN, tS, deltaN, deltaS, GI, GII, faceID, globalPatchMaterials);
895 Foam::tmp<Foam::surfaceVectorField>
896 Foam::multiMaterialCohesiveLaw::interfaceTraction
898 surfaceVectorField n,
900 volTensorField gradU,
902 volScalarField lambda
905 tmp<surfaceVectorField> tresult
907 new surfaceVectorField
912 mesh().time().timeName(),
918 dimensionedVector("zero", dimForce/dimArea, vector::zero)
921 surfaceVectorField& result = tresult();
923 surfaceScalarField mu1 = fvc::interpolate(mu);
924 surfaceScalarField lambda1 = fvc::interpolate(lambda);
926 surfaceTensorField sGradU =
927 ((I - n*n)&fvc::interpolate(gradU));
929 vectorField UI = U.internalField();
932 // (2*mu1 + lambda1)*fvc::snGrad(U)
933 // - (mu1 + lambda1)*(n&sGradU)
935 // + lambda1*tr(sGradU)*n;
938 *(n&fvc::interpolate(symm(gradU)))
939 + lambda1*n*fvc::interpolate(tr(gradU));
941 // const labelList& owner = mesh().owner();
942 //const labelList& neighbour = mesh().neighbour();
944 /* forAll(result.internalField(), faceI)
946 label ownerMat = materials_[owner[faceI]];
947 label neighbourMat = materials_[neighbour[faceI]];
949 if (ownerMat != neighbourMat)
951 vector ownN = n.internalField()[faceI];
952 vector ngbN = -n.internalField()[faceI];
955 ((I-ownN*ownN)&gradU.internalField()[owner[faceI]]);
957 ((I-ngbN*ngbN)&gradU.internalField()[neighbour[faceI]]);
959 scalar ownTrSGradUt = tr(ownSGradU&(I-ownN*ownN));
960 scalar ngbTrSGradUt = tr(ngbSGradU&(I-ngbN*ngbN));
962 vector ownSGradUn = (ownSGradU&ownN);
963 vector ngbSGradUn = (ngbSGradU&ngbN);
965 scalar ownMu = mu.internalField()[owner[faceI]];
966 scalar ngbMu = mu.internalField()[neighbour[faceI]];
968 scalar ownLambda = lambda.internalField()[owner[faceI]];
969 scalar ngbLambda = lambda.internalField()[neighbour[faceI]];
971 vector ownUt = ((I-ownN*ownN)&UI[owner[faceI]]);
972 vector ngbUt = ((I-ngbN*ngbN)&UI[neighbour[faceI]]);
974 vector ownUn = ownN*(ownN&U.internalField()[owner[faceI]]);
975 vector ngbUn = ngbN*(ngbN&U.internalField()[neighbour[faceI]]);
977 scalar ownDn = mesh().weights().internalField()[faceI]
978 * (1.0/mesh().deltaCoeffs().internalField()[faceI]);
980 (1.0/mesh().deltaCoeffs().internalField()[faceI]) - ownDn;
982 scalar own2ML = (2*ownMu + ownLambda);
983 scalar ngb2ML = (2*ngbMu + ngbLambda);
985 scalar face2ML = 1.0/((1.0-mesh().weights().internalField()[faceI])
986 / own2ML + mesh().weights().internalField()[faceI]/ngb2ML);
987 scalar faceMu = 1.0/((1.0-mesh().weights().internalField()[faceI])
988 / ownMu + mesh().weights().internalField()[faceI]/ngbMu);
991 face2ML*(ownUn - ngbUn)/(ownDn+ngbDn)
992 + ((own2ML*ngbDn*ngbLambda*ngbN*ngbTrSGradUt)
993 + (ngb2ML*ownDn*ownLambda*ngbN*ownTrSGradUt))
994 / ((own2ML*ngbDn) + (ngb2ML*ownDn));
997 faceMu*(ownUt - ngbUt)/(ownDn+ngbDn)
998 + ((ownMu*ngbMu*ngbDn*ngbSGradUn)
999 + (ownMu*ngbMu*ownDn*ownSGradUn))
1000 / ((ownMu*ngbDn) + (ngbMu*ownDn));
1002 // Info << tractionN << " *** " << tractionT <<endl;
1004 result[faceI] = tractionN + tractionT;
1005 //vector traction = tractionN + tractionT;
1008 mesh().C()[neighbour[faceI]] - mesh().C()[owner[faceI]];
1013 // cracks and bi-material interfaces may be on processor boundaries
1014 // so we must correct tractions there too
1015 forAll(mesh().boundary(), patchI)
1018 //if (mesh().boundaryMesh()[patchI].type() == processorPolyPatch::typeName)
1019 if (mesh().boundary()[patchI].coupled())
1021 const scalarField ownerMatField =
1022 materials_.boundaryField()[patchI].patchInternalField();
1023 const scalarField neighbourMatField =
1024 materials_.boundaryField()[patchI].patchNeighbourField();
1025 const labelList& faceCells = mesh().boundary()[patchI].faceCells();
1026 const tensorField ngbGradUField =
1027 gradU.boundaryField()[patchI].patchNeighbourField();
1028 const scalarField ngbMuField =
1029 mu.boundaryField()[patchI].patchNeighbourField();
1030 const scalarField ngbLambdaField =
1031 lambda.boundaryField()[patchI].patchNeighbourField();
1032 const vectorField ngbUField =
1033 U.boundaryField()[patchI].patchNeighbourField();
1034 const scalarField weights = mesh().weights().boundaryField()[patchI];
1036 forAll(mesh().boundaryMesh()[patchI], faceI)
1038 label faceCelli = faceCells[faceI];
1039 label ownerMat = ownerMatField[faceI];
1040 label neighbourMat = neighbourMatField[faceI];
1042 if (ownerMat != neighbourMat)
1044 const vector& ownN = n.boundaryField()[patchI][faceI];
1045 const vector& ngbN = -n.boundaryField()[patchI][faceI];
1046 const tensor& ngbGradU = ngbGradUField[faceI];
1047 const vector& ngbU = ngbUField[faceI];
1049 //tensor ownSGradU =
1050 // ((I-ownN*ownN)&gradU.boundaryField()[patchI][owner[faceI]]);
1051 tensor ownSGradU = ((I-ownN*ownN)&gradU.internalField()[faceCelli]);
1052 //tensor ngbSGradU =
1053 // ((I-ngbN*ngbN)&gradU.boundaryField()[patchI][neighbour[faceI]]);
1054 tensor ngbSGradU = ((I-ngbN*ngbN)&ngbGradU);
1056 scalar ownTrSGradUt = tr(ownSGradU&(I-ownN*ownN));
1057 scalar ngbTrSGradUt = tr(ngbSGradU&(I-ngbN*ngbN));
1059 vector ownSGradUn = (ownSGradU&ownN);
1060 vector ngbSGradUn = (ngbSGradU&ngbN);
1062 scalar ownMu = mu.internalField()[faceCelli];
1063 //scalar ngbMu = mu.boundaryField()[patchI][neighbour[faceI]];
1064 scalar ngbMu = ngbMuField[faceI];
1066 scalar ownLambda = lambda.internalField()[faceCelli];
1067 //scalar ngbLambda =
1068 //lambda.boundaryField()[patchI][neighbour[faceI]];
1069 scalar ngbLambda = ngbLambdaField[faceI];
1071 vector ownUt = ((I-ownN*ownN)&UI[owner[faceI]]);
1072 //vector ngbUt = ((I-ngbN*ngbN)&UI[neighbour[faceI]]);
1073 vector ngbUt = ((I-ngbN*ngbN)&ngbU);
1075 vector ownUn = ownN*(ownN&U.internalField()[faceCelli]);
1077 //ngbN*(ngbN&U.boundaryField()[patchI][neighbour[faceI]]);
1078 vector ngbUn = ngbN*(ngbN&ngbU);
1080 //scalar ownDn = mesh().weights().boundaryField()[patchI][faceI]
1081 scalar ownDn = weights[faceI]
1082 * (1.0/mesh().deltaCoeffs().boundaryField()[patchI][faceI]);
1084 (1.0/mesh().deltaCoeffs().boundaryField()[patchI][faceI]) - ownDn;
1086 scalar own2ML = (2*ownMu + ownLambda);
1087 scalar ngb2ML = (2*ngbMu + ngbLambda);
1090 // 1.0/((1.0-mesh().weights().boundaryField()[patchI][faceI])
1092 //+ mesh().weights().boundaryField()[patchI][faceI]/ngb2ML);
1093 scalar face2ML = 1.0/((1.0-weights[faceI])
1094 / own2ML + weights[faceI]/ngb2ML);
1096 // 1.0/((1.0-mesh().weights().boundaryField()[patchI][faceI])
1097 // / ownMu + mesh().weights().boundaryField()[patchI][faceI]/ngbMu);
1098 scalar faceMu = 1.0/((1.0-weights[faceI])
1099 / ownMu + weights[faceI]/ngbMu);
1102 face2ML*(ownUn - ngbUn)/(ownDn+ngbDn)
1103 + ((own2ML*ngbDn*ngbLambda*ngbN*ngbTrSGradUt)
1104 + (ngb2ML*ownDn*ownLambda*ngbN*ownTrSGradUt))
1105 / ((own2ML*ngbDn) + (ngb2ML*ownDn));
1108 faceMu*(ownUt - ngbUt)/(ownDn+ngbDn)
1109 + ((ownMu*ngbMu*ngbDn*ngbSGradUn)
1110 + (ownMu*ngbMu*ownDn*ownSGradUn))
1111 / ((ownMu*ngbDn) + (ngbMu*ownDn));
1113 result.boundaryField()[patchI][faceI] = tractionN + tractionT;
1119 if (mesh().boundary()[patchI].type() == cohesiveFvPatch::typeName)
1121 // I think mu and lambda are wrong on new crack faces
1122 // so use internal cell values
1123 const scalarField muPatch =
1124 mu.boundaryField()[patchI].patchInternalField();
1125 const scalarField lambdaPatch =
1126 lambda.boundaryField()[patchI].patchInternalField();
1127 result.boundaryField()[patchI] =
1128 (2*muPatch*n.boundaryField()[patchI]
1129 &symm(gradU.boundaryField()[patchI]))
1130 + (lambdaPatch*tr(gradU.boundaryField()[patchI])
1131 *n.boundaryField()[patchI]);
1139 void Foam::multiMaterialCohesiveLaw::correct()
1141 PtrList<cohesiveLaw>& laws = *this;
1145 laws[lawI].correct();
1150 // ************************************************************************* //