12 cumulativeContErr = 0;
19 argsPtr =
new Foam::argList(argc,argv,
true,
true, my_window_comm);
21 Info <<
"FsiFoam:Initialize: Error: Failed to create args object." << endl;
24 if (!argsPtr->checkRootCase()){
25 Info <<
"FsiFoam:Initialize: Error: Root case setup failed." << endl;
32 Foam::Info<<
"Create time\n" << Foam::endl;
33 Foam::argList &args(*argsPtr);
34 runTimePtr =
new Foam::Time
36 Foam::Time::controlDictName,
41 !args.optionFound(
"noFunctionObjects")
44 Info <<
"FsiFoam:Initialize: Error: Failed to setup time object." << endl;
56 InitTransportProperties();
67 CreateStructuresFields();
72 ReadCouplingProperties();
77 CreateInterZoneInterpolators();
84 FindGlobalFaceZones();
88 CreateFSISurfaceMesh();
90 Foam::Info <<
"End of initialization of openFoamPar module." << endl;
96 Foam::Time &runTime(*runTimePtr);
97 Info <<
"FsiFoam:Initialize: Create dynamic mesh for time = "
98 << runTime.timeName() << endl;
103 meshPtr = dynamicFvMesh::New(IOobject(dynamicFvMesh::defaultRegion,
106 IOobject::MUST_READ));
112 Foam::Time &runTime(*runTimePtr);
113 dynamicFvMesh &mesh = meshPtr();
114 Info <<
"FsiFoam:Initialize: Reading transportProperties" << endl;
115 transportPropertiesPtr =
new IOdictionary(IOobject(
"transportProperties",
119 IOobject::NO_WRITE));
125 Foam::Time &runTime(*runTimePtr);
126 dynamicFvMesh &fluidsMesh = meshPtr();
127 IOdictionary &transportProperties(*transportPropertiesPtr);
130 nuPtr =
new dimensionedScalar(transportProperties.lookup(
"nu"));
131 rhoFluidPtr =
new dimensionedScalar(transportProperties.lookup(
"rho"));
133 Info <<
"FsiFoam:CreateFluidFields: Reading field p" << endl;
138 pPtr =
new volScalarField(IOobject(
"p",
142 IOobject::AUTO_WRITE),
145 volScalarField &p(*pPtr);
147 Info <<
"FsiFoam:CreateFluidFields: Reading field U" << endl;
152 UPtr =
new volVectorField(IOobject(
"U",runTime.timeName(),fluidsMesh,
153 IOobject::MUST_READ,IOobject::AUTO_WRITE),fluidsMesh);
155 volVectorField &U = *UPtr;
158 Info <<
"FsiFoam:CreateFluidFields: Reading/calculating face flux field phi" << endl;
160 phiPtr =
new surfaceScalarField(IOobject(
"phi",runTime.timeName(),fluidsMesh,
161 IOobject::READ_IF_PRESENT,IOobject::AUTO_WRITE),
162 linearInterpolate(U) & fluidsMesh.Sf());
166 setRefCell(p, fluidsMesh.solutionDict().subDict(
"PISO"), pRefCell, pRefValue);
171 Foam::Time &runTime(*runTimePtr);
172 stressMeshPtr =
new fvMesh(IOobject(
"solid",runTime.timeName(),runTime,IOobject::MUST_READ));
173 return(stressMeshPtr != NULL);
177 Foam::Time &runTime(*runTimePtr);
178 fvMesh &structMesh(*stressMeshPtr);
180 Info <<
"FsiFoam:CreateStructuresFields: Reading incremental displacement field DU" << endl;
185 DUPtr =
new volVectorField(IOobject(
"DU",runTime.timeName(),structMesh,
186 IOobject::MUST_READ,IOobject::AUTO_WRITE),
189 volVectorField &DURef(*DUPtr);
193 gradDUPtr =
new volTensorField(fvc::grad(DURef));
194 volTensorField &gradDURef(*gradDUPtr);
196 UsolidPtr =
new volVectorField(IOobject(
"Usolid",runTime.timeName(),structMesh,
197 IOobject::READ_IF_PRESENT,IOobject::AUTO_WRITE),
201 Info <<
"FsiFoam:CreateStructuresFields: Reading incremental displacement field DV" << endl;
202 DVPtr =
new volVectorField(IOobject(
"DV",runTime.timeName(),structMesh,
203 IOobject::READ_IF_PRESENT,IOobject::AUTO_WRITE),
207 Info <<
"FsiFoam:CreateStructuresFields: Reading accumulated velocity field V" << endl;
208 VsPtr =
new volVectorField(IOobject(
"Vs",runTime.timeName(),structMesh,
209 IOobject::READ_IF_PRESENT,IOobject::AUTO_WRITE),
211 dimensionedVector(
"zero",dimVelocity,vector::zero));
214 Info <<
"FsiFoam:CreateStructuresFields: Reading accumulated stress field sigma" << endl;
215 sigmaPtr =
new volSymmTensorField(IOobject(
"sigma",runTime.timeName(),structMesh,
216 IOobject::READ_IF_PRESENT,IOobject::AUTO_WRITE),
218 dimensionedSymmTensor(
"zero",dimForce/dimArea,symmTensor::zero));
219 volSymmTensorField &sigmaref(*sigmaPtr);
222 Info <<
"FsiFoam:CreateStructuresFields: Reading incremental stress field DSigma" << endl;
223 DSigmaPtr =
new volSymmTensorField(IOobject(
"DSigma",runTime.timeName(),structMesh,
224 IOobject::READ_IF_PRESENT,IOobject::AUTO_WRITE),
226 dimensionedSymmTensor(
"zero",dimForce/dimArea,symmTensor::zero));
229 rheologyPtr =
new constitutiveModel(sigmaref,DURef);
231 constitutiveModel &rheology(*rheologyPtr);
235 rhoPtr =
new volScalarField(rheology.rho());
236 muPtr =
new volScalarField(rheology.mu());
237 lambdaPtr =
new volScalarField(rheology.lambda());
239 FPtr =
new volTensorField(I + gradDURef.T());
240 volTensorField &FRef(*FPtr);
241 DFPtr =
new volTensorField(FRef - I);
242 JPtr =
new volScalarField(det(FRef));
244 solidDdtSchemePtr =
new word(structMesh.schemesDict().ddtScheme(
"ddt("+DURef.name()+
')'));
248 Foam::argList &args(*argsPtr);
249 Foam::Time &runTime(*runTimePtr);
250 dynamicFvMesh &fluidMesh(meshPtr());
251 fvMesh &structMesh(*stressMeshPtr);
253 Info <<
"FsiFoam:ReadCouplingProperties: Reading coupling properties" << endl;
255 couplingPropertiesPtr =
new IOdictionary(IOobject(
"couplingProperties",runTime.constant(),
256 fluidMesh,IOobject::MUST_READ,IOobject::NO_WRITE));
257 IOdictionary &couplingProperties(*couplingPropertiesPtr);
259 solidPatchName = word(couplingProperties.lookup(
"solidPatch"));
260 solidPatchID = structMesh.boundaryMesh().findPatchID(solidPatchName);
262 if (solidPatchID < 0)
264 FatalErrorIn(args.executable())
265 <<
"FsiFoam:ReadCouplingProperties: Problem with finding solid patch"
266 << abort(FatalError);
269 solidZoneName = word(couplingProperties.lookup(
"solidZone"));
273 structMesh.faceZones().findZoneID(solidZoneName);
277 FatalErrorIn(args.executable())
278 <<
"FsiFoam:ReadCouplingProperties: Problem with finding solid zone"
279 << abort(FatalError);
282 fluidPatchName = word(couplingProperties.lookup(
"fluidPatch"));
283 fluidPatchID = fluidMesh.boundaryMesh().findPatchID(fluidPatchName);
286 if (fluidPatchID < 0)
288 FatalErrorIn(args.executable())
289 <<
"FsiFoam:ReadCouplingProperties: Problem with finding fluid patch"
290 << abort(FatalError);
293 fluidZoneName = word(couplingProperties.lookup(
"fluidZone"));
294 fluidZoneID = fluidMesh.faceZones().findZoneID(fluidZoneName);
297 FatalErrorIn(args.executable())
298 <<
"FsiFoam:ReadCouplingProperties: Problem with finding fluid zone"
299 << abort(FatalError);
302 feMotionSolver = fluidMesh.objectRegistry::foundObject<tetPointVectorField>(
"motionU");
303 fvMotionSolver = fluidMesh.objectRegistry::foundObject<pointVectorField>(
"pointMotionU");
311 Info <<
"FsiFoam:ReadCouplingProperties:Solid patch ID: " << solidPatchID << endl;
312 volVectorField &DURef(*DUPtr);
315 DURef.boundaryField()[solidPatchID].type()
316 != solidTractionFvPatchVectorField::typeName
320 FatalErrorIn(args.executable())
321 <<
"FsiFoam:ReadCouplingProperties: Boundary condition on " << DURef.name()
323 << DURef.boundaryField()[solidPatchID].type()
324 <<
"for fluid -solid interface patch, instead "
325 << solidTractionFvPatchVectorField::typeName
327 << abort(FatalError);
336 accumulatedFluidInterfaceDisplacementHeaderPtr =
new IOobject(
"accumulatedFluidInterfaceDisplacement",
339 IOobject::MUST_READ);
340 IOobject &accumulatedFluidInterfaceDisplacementHeader(*accumulatedFluidInterfaceDisplacementHeaderPtr);
344 if(accumulatedFluidInterfaceDisplacementHeader.headerOk())
346 Pout <<
"FsiFoam:ReadCouplingProperties: Reading accumulated fluid interface displacement" << endl;
348 accumulatedFluidInterfaceDisplacementPtr =
353 "accumulatedFluidInterfaceDisplacement",
363 accumulatedFluidInterfaceDisplacementPtr =
368 "accumulatedFluidInterfaceDisplacement",
377 fluidMesh.boundaryMesh()[fluidPatchID].nPoints(),
396 dynamicFvMesh &fluidMesh = meshPtr();
397 fvMesh &structMesh(*stressMeshPtr);
399 if(!interpolatorFluidSolidPtr || !interpolatorSolidFluidPtr)
401 deleteDemandDrivenData(interpolatorFluidSolidPtr);
402 deleteDemandDrivenData(interpolatorSolidFluidPtr);
404 Info <<
"FsiFoam:CreateInterZoneInterpolators: Create fluid-to-solid and solid-to-fluid interpolators" << endl;
406 interpolatorFluidSolidPtr =
new zoneToZoneInterpolation
408 fluidMesh.faceZones()[fluidZoneID](),
409 structMesh.faceZones()[solidZoneID](),
410 intersection::VISIBLE
413 interpolatorSolidFluidPtr =
new zoneToZoneInterpolation
415 structMesh.faceZones()[solidZoneID](),
416 fluidMesh.faceZones()[fluidZoneID](),
417 intersection::VISIBLE
420 Info <<
"FsiFoam:CreateInterZoneInterpolators: Check fluid-to-solid and solid-to-fluid interpolators" << endl;
423 vectorField fluidPatchFaceCentres =
424 vectorField(fluidMesh.boundaryMesh()[fluidPatchID].faceCentres());
426 vectorField fluidZoneFaceCentres
428 fluidMesh.faceZones()[fluidZoneID].size(),
433 const label fluidPatchStart =
434 fluidMesh.boundaryMesh()[fluidPatchID].start();
436 forAll (fluidPatchFaceCentres, i)
440 fluidMesh.faceZones()[fluidZoneID].whichFace(fluidPatchStart + i)
442 fluidPatchFaceCentres[i];
446 reduce(fluidZoneFaceCentres, sumOp<vectorField>());
448 vectorField solidZoneFaceCentres =
449 interpolatorFluidSolidPtr->faceInterpolate
454 vectorField solidPatchFaceCentres
456 structMesh.boundaryMesh()[solidPatchID].size(),
460 const label solidPatchStart =
461 structMesh.boundaryMesh()[solidPatchID].start();
463 forAll(solidPatchFaceCentres, i)
465 solidPatchFaceCentres[i] =
468 structMesh.faceZones()[solidZoneID]
469 .whichFace(solidPatchStart + i)
473 scalar maxDist = gMax
477 solidPatchFaceCentres
478 - structMesh.boundaryMesh()[solidPatchID].faceCentres()
482 Info <<
"FsiFoam:CreateInterZoneInterpolators: Fluid-to-solid face interpolation error: " << maxDist
489 vectorField solidPatchFaceCentres =
490 vectorField(structMesh.boundaryMesh()[solidPatchID].faceCentres());
492 vectorField solidZoneFaceCentres
494 structMesh.faceZones()[solidZoneID].size(),
498 const label solidPatchStart =
499 structMesh.boundaryMesh()[solidPatchID].start();
501 forAll (solidPatchFaceCentres, i)
505 structMesh.faceZones()[solidZoneID]
506 .whichFace(solidPatchStart + i)
508 solidPatchFaceCentres[i];
512 reduce(solidZoneFaceCentres, sumOp<vectorField>());
514 vectorField fluidZoneFaceCentres =
515 interpolatorSolidFluidPtr->faceInterpolate
520 vectorField fluidPatchFaceCentres
522 fluidMesh.boundaryMesh()[fluidPatchID].size(),
526 const label fluidPatchStart =
527 fluidMesh.boundaryMesh()[fluidPatchID].start();
529 forAll(fluidPatchFaceCentres, i)
531 fluidPatchFaceCentres[i] =
534 fluidMesh.faceZones()[fluidZoneID]
535 .whichFace(fluidPatchStart + i)
539 scalar maxDist = gMax
543 fluidPatchFaceCentres
544 - fluidMesh.boundaryMesh()[fluidPatchID].faceCentres()
548 Info <<
"FsiFoam:CreateInterZoneInterpolators: Solid-to-fluid face interpolation error: " << maxDist
560 fvMesh &structMesh(*stressMeshPtr);
561 Foam::argList &args = *argsPtr;
564 SLList<label> globalFaceZonesSet;
566 const faceZoneMesh& faceZones = structMesh.faceZones();
568 forAll(faceZones, zoneI)
570 const faceZone& curFaceZone = faceZones[zoneI];
572 forAll(curFaceZone, faceI)
575 if (curFaceZone[faceI] >= structMesh.nFaces())
577 globalFaceZonesSet.insert(zoneI);
583 globalFaceZones = labelList(globalFaceZonesSet);
585 globalToLocalFaceZonePointMap.resize(globalFaceZones.size());
587 forAll(globalFaceZones, zoneI)
589 label curZoneID = globalFaceZones[zoneI];
590 labelList curMap(structMesh.faceZones()[curZoneID]().nPoints(), -1);
591 vectorField fzGlobalPoints =
592 structMesh.faceZones()[curZoneID]().localPoints();
595 if(!Pstream::master())
597 fzGlobalPoints *= 0.0;
601 reduce(fzGlobalPoints, sumOp<vectorField>());
606 const vectorField& fzLocalPoints =
607 structMesh.faceZones()[curZoneID]().localPoints();
608 const edgeList& fzLocalEdges =
609 structMesh.faceZones()[curZoneID]().edges();
610 const labelListList& fzPointEdges =
611 structMesh.faceZones()[curZoneID]().pointEdges();
612 scalarField minEdgeLength(fzLocalPoints.size(), GREAT);
614 forAll(minEdgeLength, pI)
616 const labelList& curPointEdges = fzPointEdges[pI];
617 forAll(curPointEdges, eI)
619 scalar Le = fzLocalEdges[curPointEdges[eI]].mag(fzLocalPoints);
620 if (Le < minEdgeLength[pI])
622 minEdgeLength[pI] = Le;
627 forAll(fzGlobalPoints, globalPointI)
631 forAll(fzLocalPoints, procPointI)
636 fzLocalPoints[procPointI]
637 - fzGlobalPoints[globalPointI]
645 if (curDist < 1e-4*minEdgeLength[procPointI])
647 curMap[globalPointI] = procPointI;
658 forAll(curMap, globalPointI)
660 if (curMap[globalPointI] == -1)
662 FatalErrorIn(args.executable())
663 <<
"FsiFoam:FindGlobalFaceZones: local to global face zone point map is not correct"
664 << abort(FatalError);
668 globalToLocalFaceZonePointMap[zoneI] = curMap;
674 dynamicFvMesh &fluidMesh(meshPtr());
675 dictionary &piso(fluidMesh.solutionDict().subDict(
"PISO"));
677 nCorr = readInt(piso.lookup(
"nCorrectors"));
678 nNonOrthCorr = piso.lookupOrDefault<
int>(
"nNonOrthogonalCorrectors", 0);
679 momentumPredictor = piso.lookupOrDefault<Switch>(
"momentumPredictor",
true);
680 transonic = piso.lookupOrDefault<Switch>(
"transonic",
false);
681 nOuterCorr = piso.lookupOrDefault<
int>(
"nOuterCorrectors", 1);
687 IOdictionary &couplingProperties(*couplingPropertiesPtr);
691 if (couplingProperties.found(
"couplingScheme"))
693 couplingScheme = word(couplingProperties.lookup(
"couplingScheme"));
696 (couplingScheme ==
"IQN-ILS")
697 || (couplingScheme ==
"Aitken")
698 || (couplingScheme ==
"FixedRelaxation")
699 || (couplingScheme ==
"NonIterative")
702 Info<<
"FsiFoam:ReadFSIControl: Selecting coupling scheme " << couplingScheme << endl;
709 ) <<
"couplingScheme: " << couplingScheme
710 <<
" is not a valid choice. "
711 <<
"Options are: IQN-ILS, Aitken, FixedRelaxation"
712 << abort(FatalError);
716 interfaceDeformationLimit =
717 scalar(readScalar(couplingProperties.lookup(
"interfaceDeformationLimit")));
734 fsiRelaxationFactorMin = scalar(readScalar(couplingProperties.lookup(
"fsiRelaxationFactor")));
735 fsiRelaxationFactor = fsiRelaxationFactorMin;
736 outerCorrTolerance = scalar(readScalar(couplingProperties.lookup(
"outerCorrTolerance")));
737 Info <<
"FsiFoam:ReadFSIControl: outerCorrTolerance = " << outerCorrTolerance << endl;
738 fsi = Switch(couplingProperties.lookup(
"fsi"));
740 Info <<
"FsiFoam:ReadFSIControl: FSI IS ENABLED." << endl;
742 Info <<
"FsiFoam:ReadFSIControl: FSI IS DISABLED." << endl;
747 Foam::argList &args(this->ArgList());
748 Foam::Time &runTime(this->RunTime());
749 dynamicFvMesh &fluidsMesh(this->FluidMesh());
751 dimensionedScalar &nu(this->nu());
752 dimensionedScalar &rhoFluid(this->rhoFluid());
753 volScalarField &p(this->p());
754 volVectorField &U(this->U());
755 surfaceScalarField &phi(this->phi());
760 fvMesh &structuresMesh(this->StructuresMesh());
763 volVectorField &DU(this->DU());
764 volTensorField &gradDU(this->gradDU());
765 volVectorField &Usolid(this->Usolid());
766 volVectorField &DV(this->DV());
767 volVectorField &Vs(this->Vs());
768 volSymmTensorField &sigma(this->sigma());
769 volSymmTensorField &DSigma(this->DSigma());
771 volScalarField &rho(this->rhoSolid());
772 volScalarField &mu(this->mu());
773 volScalarField &lambda(this->lambda());
774 volTensorField &F(this->F());
775 volTensorField &DF(this->DF());
776 volScalarField &J(this->J());
777 word &solidDdtScheme(this->SolidDdtScheme());
783 label solidPatchID(this->SolidPatchID());
785 label fluidPatchID(this->FluidPatchID());
787 label fluidZoneID(this->FluidZoneID());
788 label solidZoneID(this->SolidZoneID());
790 bool feMotionSolver(this->FEMotion());
791 bool fvMotionSolver(this->FVMotion());
792 vectorField &accumulatedFluidInterfaceDisplacement(this->AccumulatedFluidInterfaceDisplacements());
793 Info <<
"FsiFoam:Step: accumulatedFluidInterfaceDisplacement = " << endl;
794 Info << accumulatedFluidInterfaceDisplacement << endl;
795 solidTractionFvPatchVectorField &tForce(this->tForce());
797 zoneToZoneInterpolation &interpolatorFluidSolid(this->interpFluidSolid());
798 zoneToZoneInterpolation &interpolatorSolidFluid(this->interpSolidFluid());
800 scalar &sumLocalContErr(this->LocalContErr());
801 scalar &globalContErr(this->GlobalContErr());
802 scalar &cumulativeContErr(this->CumulativeContErr());
804 labelList &globalFaceZones(this->GlobalFaceZones());
805 labelListList &globalToLocalFaceZonePointMap(this->GlobalToLocalFaceZonePointMap());
816 this->ReadPISOControls();
817 this->ReadFSIControls();
818 word couplingScheme(this->CouplingScheme());
820 scalar &fsiRelaxationFactor(this->FSIRelaxationFactor());
822 Switch fsi(this->FSIEnabled());
823 int &nCorrPISO(this->NCorrPISO());
824 int &nNonOrthCorr(this->NNonOrthCorr());
825 scalar &interfaceDeformationLimit(this->InterfaceDeformationLimit());
826 scalar &outerCorrTolerance(this->OuterCorrTolerance());
827 int &nOuterCorr(this->NOuterCorr());
833 pointMesh StructuresPointMesh(structuresMesh);
835 pointPatchInterpolation patchPointInterpolator(structuresMesh);
842 StructuresPointMesh.boundary().size(),
843 calculatedFvPatchVectorField::typeName
848 forAll(DU.boundaryField().types(), patchI)
852 DU.boundaryField().types()[patchI]
853 == fixedValueFvPatchVectorField::typeName
856 types[patchI] = fixedValueFvPatchVectorField::typeName;
860 pointVectorField pointDU
869 dimensionedVector(
"zero", dimLength, vector::zero),
873 vectorField fluidPatchPointsDispl
875 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
879 vectorField fluidPatchPointsDisplOld
881 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
885 vectorField solidPatchPointsDispl
887 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
891 vectorField fsiResidual
893 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
897 vectorField fsiResidualOld
899 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
903 vectorField solidPatchTraction
905 structuresMesh.boundary()[solidPatchID].size(),
909 scalarField solidPatchPressure
911 structuresMesh.boundary()[solidPatchID].size(),
915 scalar initialFsiResidualNorm = 0;
916 scalar fsiResidualNorm = 0;
924 Info <<
"\nTime = " << runTime.timeName()
925 <<
", iteration: " << outerCorr << endl;
927 if (outerCorr < 3 || couplingScheme ==
"FixedRelaxation")
929 Info <<
"FsiFoam:Step: Current fsi under-relaxation factor: "
930 << fsiRelaxationFactor << endl;
932 fluidPatchPointsDisplOld = fluidPatchPointsDispl;
934 fluidPatchPointsDispl += fsiRelaxationFactor*fsiResidual;
938 if (couplingScheme ==
"Aitken")
940 fsiRelaxationFactor =
946 &(fsiResidual - fsiResidualOld)
951 (fsiResidual - fsiResidualOld)
952 &(fsiResidual - fsiResidualOld)
957 fsiRelaxationFactor = mag(fsiRelaxationFactor);
959 Info <<
"FsiFoam:Step: Current fsi under-relaxation factor (Aitken): "
960 << fsiRelaxationFactor << endl;
962 fluidPatchPointsDisplOld = fluidPatchPointsDispl;
964 fluidPatchPointsDispl +=
965 fsiRelaxationFactor*fsiResidual;
976 const vectorField& n =
977 fluidsMesh.boundaryMesh()[fluidPatchID].pointNormals();
979 primitivePatchInterpolation patchInterpolator
981 fluidsMesh.boundaryMesh()[fluidPatchID]
984 scalarField pointDeltaCoeffs =
985 patchInterpolator.faceToPointInterpolate
987 fluidsMesh.boundary()[fluidPatchID].deltaCoeffs()
997 accumulatedFluidInterfaceDisplacement
998 + fluidPatchPointsDispl
999 - fluidPatchPointsDisplOld
1005 Info <<
"FsiFoam:Step: Maximal accumulated displacement of interface points: "
1008 if(delta < interfaceDeformationLimit)
1012 Info <<
"FsiFoam:Step: Moving only interface points..." << endl;
1014 pointField newPoints = fluidsMesh.allPoints();
1016 const labelList& meshPoints =
1017 fluidsMesh.boundaryMesh()[fluidPatchID].meshPoints();
1019 forAll (fluidPatchPointsDispl, pointI)
1023 newPoints[meshPoints[pointI]] +=
1024 fluidPatchPointsDispl[pointI]
1025 - fluidPatchPointsDisplOld[pointI];
1028 twoDPointCorrector twoDCorrector(fluidsMesh);
1030 twoDCorrector.correctPoints(newPoints);
1032 fluidsMesh.movePoints(newPoints);
1035 accumulatedFluidInterfaceDisplacement +=
1036 fluidPatchPointsDispl
1037 - fluidPatchPointsDisplOld;
1042 Info <<
"FsiFoam:Step: Moving the whole mesh .... " << endl;
1043 pointField newPoints = fluidsMesh.allPoints();
1045 const labelList& meshPoints =
1046 fluidsMesh.boundaryMesh()[fluidPatchID].meshPoints();
1048 forAll (accumulatedFluidInterfaceDisplacement, pointI)
1052 newPoints[meshPoints[pointI]] -=
1053 accumulatedFluidInterfaceDisplacement[pointI];
1056 twoDPointCorrector twoDCorrector(fluidsMesh);
1058 twoDCorrector.correctPoints(newPoints);
1060 fluidsMesh.movePoints(newPoints);
1062 accumulatedFluidInterfaceDisplacement +=
1063 fluidPatchPointsDispl
1064 - fluidPatchPointsDisplOld;
1069 tetPointVectorField& motionU =
1070 const_cast<tetPointVectorField&
>
1072 fluidsMesh.objectRegistry::
lookupObject<tetPointVectorField>
1078 fixedValueTetPolyPatchVectorField& motionUFluidPatch =
1079 refCast<fixedValueTetPolyPatchVectorField>
1081 motionU.boundaryField()[fluidPatchID]
1084 tetPolyPatchInterpolation tppi
1086 refCast<const faceTetPolyPatch>(motionUFluidPatch.patch())
1089 motionUFluidPatch ==
1090 tppi.pointToPointInterpolate
1092 accumulatedFluidInterfaceDisplacement
1093 /runTime.deltaT().value()
1096 else if (fvMotionSolver)
1098 pointVectorField& motionU =
1099 const_cast<pointVectorField&
>
1101 fluidsMesh.objectRegistry::
lookupObject<pointVectorField>
1107 fixedValuePointPatchVectorField& motionUFluidPatch =
1108 refCast<fixedValuePointPatchVectorField>
1110 motionU.boundaryField()[fluidPatchID]
1113 motionUFluidPatch ==
1114 accumulatedFluidInterfaceDisplacement
1115 /runTime.deltaT().value();
1119 FatalErrorIn(args.executable())
1120 <<
"FsiFoam:Step: Problem with mesh motion solver selection"
1121 << abort(FatalError);
1124 fluidsMesh.update();
1126 accumulatedFluidInterfaceDisplacement = vector::zero;
1133 if(fluidsMesh.moving())
1136 phi -= fvc::meshPhi(U);
1142 scalar meanCoNum = 0.0;
1143 scalar velMag = 0.0;
1145 if (fluidsMesh.nInternalFaces())
1147 surfaceScalarField magPhi = mag(phi);
1149 surfaceScalarField SfUfbyDelta =
1150 fluidsMesh.surfaceInterpolation::deltaCoeffs()*magPhi;
1152 const scalar deltaT = runTime.deltaT().value();
1154 CoNum = max(SfUfbyDelta/fluidsMesh.magSf()).value()*deltaT;
1156 meanCoNum = (sum(SfUfbyDelta)/sum(fluidsMesh.magSf())).value()*deltaT;
1158 velMag = max(magPhi/fluidsMesh.magSf()).value();
1161 Info<<
"FsiFoam:Step: Courant Number mean: " << meanCoNum
1162 <<
" max: " << CoNum
1163 <<
" velocity magnitude: " << velMag
1170 - fvm::laplacian(nu, U)
1173 solve(UEqn == -fvc::grad(p));
1176 volScalarField rUA = 1.0/UEqn.A();
1178 for (
int corr=0; corr<nCorrPISO; corr++)
1181 phi = (fvc::interpolate(U) & fluidsMesh.Sf());
1183 adjustPhi(phi, U, p);
1185 for (
int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
1189 fvm::laplacian(rUA, p)
1193 pEqn.setReference(pRefCell, pRefValue);
1196 if (nonOrth == nNonOrthCorr)
1204 volScalarField contErr = fvc::div(phi);
1206 sumLocalContErr = runTime.deltaT().value()*
1207 mag(contErr)().weightedAverage(fluidsMesh.V()).value();
1209 globalContErr = runTime.deltaT().value()*
1210 contErr.weightedAverage(fluidsMesh.V()).value();
1212 cumulativeContErr += globalContErr;
1214 Info<<
"FsiFoam:Step: time step continuity errors : sum local = " << sumLocalContErr
1215 <<
", global = " << globalContErr
1216 <<
", cumulative = " << cumulativeContErr
1220 U -= rUA*fvc::grad(p);
1221 U.correctBoundaryConditions();
1228 Info <<
"FsiFoam:Step: Setting traction on solid patch" << endl;
1236 vectorField fluidPatchTraction =
1237 -rhoFluid.value()*nu.value()
1238 *U.boundaryField()[fluidPatchID].snGrad();
1242 scalarField fluidPatchPressure =
1243 rhoFluid.value()*p.boundaryField()[fluidPatchID];
1247 vectorField fluidZoneTraction
1249 fluidsMesh.faceZones()[fluidZoneID].size(),
1255 const label fluidPatchStart =
1256 fluidsMesh.boundaryMesh()[fluidPatchID].start();
1258 forAll(fluidPatchTraction, i)
1262 fluidsMesh.faceZones()[fluidZoneID].whichFace(fluidPatchStart + i)
1264 fluidPatchTraction[i];
1268 reduce(fluidZoneTraction, sumOp<vectorField>());
1271 scalarField fluidZonePressure
1273 fluidsMesh.faceZones()[fluidZoneID].size(),
1277 forAll(fluidPatchPressure, i)
1281 fluidsMesh.faceZones()[fluidZoneID].whichFace(fluidPatchStart + i)
1283 fluidPatchPressure[i];
1287 reduce(fluidZonePressure, sumOp<scalarField>());
1289 vectorField solidZoneTraction =
1290 interpolatorFluidSolid.faceInterpolate
1297 scalarField solidZonePressure =
1298 interpolatorFluidSolid.faceInterpolate
1305 const label solidPatchStart =
1306 structuresMesh.boundaryMesh()[solidPatchID].start();
1308 forAll(solidPatchTraction, i)
1310 solidPatchTraction[i] =
1313 structuresMesh.faceZones()[solidZoneID]
1314 .whichFace(solidPatchStart + i)
1318 forAll(solidPatchPressure, i)
1320 solidPatchPressure[i] =
1323 structuresMesh.faceZones()[solidZoneID]
1324 .whichFace(solidPatchStart + i)
1330 tForce.traction() = solidPatchTraction;
1331 tForce.pressure() = solidPatchPressure;
1334 vector totalTractionForce =
1338 *structuresMesh.magSf().boundaryField()[solidPatchID]
1341 Info <<
"FsiFoam:Step: Total traction force = "
1342 << totalTractionForce << endl;
1348 if (solidDdtScheme == fv::EulerDdtScheme<vector>::typeName)
1350 Info <<
"FsiFoam:Step: Solve Solid: Euler" << endl;
1353 const dictionary& stressControl =
1354 structuresMesh.solutionDict().subDict(
"solidMechanics");
1356 int nCorrStruct(readInt(stressControl.lookup(
"nCorrectors")));
1357 scalar convergenceTolerance(readScalar(stressControl.lookup(
"DU")));
1361 lduMatrix::solverPerformance solverPerf;
1362 scalar initialResidual = 0;
1364 lduMatrix::debug = 0;
1367 dimensionedScalar Cn(
"Cn", dimless/dimTime, 1.0/runTime.deltaT().value());
1368 dimensionedScalar Co(
"Co", dimless/dimTime, 1.0/runTime.deltaT().value());
1374 fvVectorMatrix DUEqn
1377 - Co*rho*DV.oldTime()
1379 fvm::laplacian(2*mu + lambda, DU,
"laplacian(DDU,DU)")
1380 - fvc::laplacian(mu + lambda, DU,
"laplacian(DDU,DU)")
1384 + lambda*(I*tr(gradDU))
1385 + mu*(gradDU&gradDU.T())
1386 + 0.5*lambda*(I*tr(gradDU & gradDU.T()))
1388 + (DSigma & DF.T()),
1393 solverPerf = DUEqn.solve();
1399 initialResidual = solverPerf.initialResidual();
1402 gradDU = fvc::grad(DU);
1408 volSymmTensorField Depsilon = symm(gradDU)
1409 + 0.5*symm(gradDU & gradDU.T());
1411 DSigma = 2*mu*Depsilon + I*(lambda*tr(Depsilon));
1416 solverPerf.initialResidual() > convergenceTolerance
1417 && ++iCorr < nCorrStruct
1420 Info <<
"FsiFoam:Step: Solving for " << DU.name()
1421 <<
", Initial residual = " << initialResidual
1422 <<
", Final residual = " << solverPerf.initialResidual()
1423 <<
", No outer iterations " << iCorr << endl;
1427 lduMatrix::debug = 1;
1430 else if (solidDdtScheme == fv::backwardDdtScheme<vector>::typeName)
1432 Info <<
"FsiFoam:Step: Solve Solid: Backward" << endl;
1437 const dictionary& stressControl =
1438 structuresMesh.solutionDict().subDict(
"solidMechanics");
1440 int nCorrStruct(readInt(stressControl.lookup(
"nCorrectors")));
1441 scalar convergenceTolerance(readScalar(stressControl.lookup(
"DU")));
1444 lduMatrix::solverPerformance solverPerf;
1445 scalar initialResidual = 0;
1447 lduMatrix::debug = 0;
1450 dimensionedScalar Cn(
"Cn", dimless/dimTime, 0.0);
1451 dimensionedScalar Co(
"Co", dimless/dimTime, 0.0);
1452 dimensionedScalar Coo(
"Coo", dimless/dimTime, 0.0);
1454 scalar deltaT = runTime.deltaT().value();
1455 scalar deltaT0 = runTime.deltaT0().value();
1457 Cn.value() = 1 + deltaT/(deltaT + deltaT0);
1458 Coo.value() = deltaT*deltaT/(deltaT0*(deltaT + deltaT0));
1459 Co.value() = Cn.value() + Coo.value();
1461 if(runTime.timeIndex() == 1)
1468 Cn.value() /= deltaT;
1469 Co.value() /= deltaT;
1470 Coo.value() /= deltaT;
1493 fvVectorMatrix DUEqn
1496 - Co*rho*DV.oldTime()
1497 + Coo*rho*DV.oldTime().oldTime()
1499 fvm::laplacian(2*mu + lambda, DU,
"laplacian(DDU,DU)")
1500 - fvc::laplacian(mu + lambda, DU,
"laplacian(DDU,DU)")
1504 + lambda*(I*tr(gradDU))
1505 + mu*(gradDU&gradDU.T())
1506 + 0.5*lambda*(I*tr(gradDU & gradDU.T()))
1508 + (DSigma & DF.T()),
1513 solverPerf = DUEqn.solve();
1519 initialResidual = solverPerf.initialResidual();
1522 gradDU = fvc::grad(DU);
1528 volSymmTensorField Depsilon = symm(gradDU)
1529 + 0.5*symm(gradDU & gradDU.T());
1531 DSigma = 2*mu*Depsilon + I*(lambda*tr(Depsilon));
1541 solverPerf.initialResidual() > convergenceTolerance
1542 && ++iCorr < nCorrStruct
1545 Info <<
"FsiFoam:Step: Solving for " << DU.name()
1546 <<
", Initial residual = " << initialResidual
1547 <<
", Final residual = " << solverPerf.initialResidual()
1548 <<
", No outer iterations " << iCorr << endl;
1552 lduMatrix::debug = 1;
1557 FatalErrorIn(args.executable())
1558 <<
"FsiFoam:Step: Wrong temporal (ddt) scheme for solid solver. "
1559 <<
"Possible schemes are: "
1560 << fv::EulerDdtScheme<vector>::typeName <<
" and "
1561 << fv::backwardDdtScheme<vector>::typeName
1562 << abort(FatalError);
1567 const vectorField& solidPatchDisplacement =
1568 DU.boundaryField()[solidPatchID];
1570 vectorField solidZoneDisplacement
1572 structuresMesh.faceZones()[solidZoneID]().size(),
1576 const label solidPatchStart =
1577 structuresMesh.boundaryMesh()[solidPatchID].start();
1579 forAll(solidPatchDisplacement, i)
1581 solidZoneDisplacement
1583 structuresMesh.faceZones()[solidZoneID]
1584 .whichFace(solidPatchStart + i)
1586 solidPatchDisplacement[i];
1590 reduce(solidZoneDisplacement, sumOp<vectorField>());
1592 vectorField fluidZoneDisplacement =
1593 interpolatorSolidFluid.faceInterpolate
1595 solidZoneDisplacement
1598 vectorField fluidPatchDisplacement
1600 fluidsMesh.boundary()[fluidPatchID].size(),
1604 const label fluidPatchStart =
1605 fluidsMesh.boundaryMesh()[fluidPatchID].start();
1607 forAll(fluidPatchDisplacement, i)
1609 fluidPatchDisplacement[i] =
1610 fluidZoneDisplacement
1612 fluidsMesh.faceZones()[fluidZoneID].whichFace(fluidPatchStart + i)
1616 primitivePatchInterpolation fluidPatchInterpolator
1618 fluidsMesh.boundaryMesh()[fluidPatchID]
1621 solidPatchPointsDispl =
1622 fluidPatchInterpolator.faceToPointInterpolate
1624 fluidPatchDisplacement
1627 fsiResidualOld = fsiResidual;
1629 fsiResidual = solidPatchPointsDispl - fluidPatchPointsDispl;
1647 fsiResidualNorm = ::sqrt(gSum(magSqr(fsiResidual)));
1651 initialFsiResidualNorm = fsiResidualNorm;
1654 fsiResidualNorm /= initialFsiResidualNorm + SMALL;
1656 Info <<
"FsiFoam:Step: Current fsi residual norm: " << fsiResidualNorm << endl;
1661 (fsiResidualNorm > outerCorrTolerance)
1662 && (outerCorr < nOuterCorr)
1669 Info <<
"FsiFoam:Step: Rotating fields" << endl;
1688 sigma = 1/J * symm(F & sigma & F.T());
1694 if(min(J.internalField()) > 0)
1696 Info <<
"FsiFoam:Step: Moving mesh using least squares interpolation" << endl;
1698 leastSquaresVolPointInterpolation pointInterpolation(structuresMesh);
1701 pointMesh pMesh(structuresMesh);
1705 pMesh.boundary().size(),
1706 calculatedFvPatchVectorField::typeName
1709 pointVectorField pointDU
1718 dimensionedVector(
"zero", dimLength, vector::zero),
1722 pointInterpolation.interpolate(DU, pointDU);
1724 const vectorField& pointDUI =
1725 pointDU.internalField();
1728 vectorField newPoints = structuresMesh.allPoints();
1730 forAll (pointDUI, pointI)
1732 newPoints[pointI] += pointDUI[pointI];
1737 forAll(structuresMesh.boundaryMesh(), patchI)
1739 if (isA<symmetryPolyPatch>(structuresMesh.boundaryMesh()[patchI]))
1741 const labelList& meshPoints =
1742 structuresMesh.boundaryMesh()[patchI].meshPoints();
1745 gAverage(structuresMesh.boundaryMesh()[patchI].pointNormals());
1751 if (mag(avgN&i) > 0.95)
1753 forAll(meshPoints, pI)
1755 newPoints[meshPoints[pI]].x() = 0;
1758 else if (mag(avgN&j) > 0.95)
1760 forAll(meshPoints, pI)
1762 newPoints[meshPoints[pI]].y() = 0;
1765 else if (mag(avgN&k) > 0.95)
1767 forAll(meshPoints, pI)
1769 newPoints[meshPoints[pI]].z() = 0;
1776 forAll(globalFaceZones, zoneI)
1778 const label curZoneID = globalFaceZones[zoneI];
1780 const labelList& curMap =
1781 globalToLocalFaceZonePointMap[zoneI];
1783 const labelList& curZoneMeshPoints =
1784 structuresMesh.faceZones()[curZoneID]().meshPoints();
1786 vectorField curGlobalZonePointDispl
1788 curZoneMeshPoints.size(),
1794 scalarField pointNumProcs(curZoneMeshPoints.size(), 0);
1796 forAll(curGlobalZonePointDispl, globalPointI)
1798 label localPoint = curMap[globalPointI];
1800 if(curZoneMeshPoints[localPoint] < structuresMesh.nPoints())
1802 label procPoint = curZoneMeshPoints[localPoint];
1804 curGlobalZonePointDispl[globalPointI] = pointDUI[procPoint];
1806 pointNumProcs[globalPointI] = 1;
1810 if (Pstream::parRun())
1812 reduce(curGlobalZonePointDispl, sumOp<vectorField>());
1813 reduce(pointNumProcs, sumOp<scalarField>());
1816 curGlobalZonePointDispl /= pointNumProcs;
1823 vectorField curZonePointDispl
1825 curZoneMeshPoints.size(),
1829 forAll(curGlobalZonePointDispl, globalPointI)
1831 label localPoint = curMap[globalPointI];
1833 curZonePointDispl[localPoint] =
1834 curGlobalZonePointDispl[globalPointI];
1837 forAll(curZonePointDispl, pointI)
1840 if (curZoneMeshPoints[pointI] >= structuresMesh.nPoints())
1842 newPoints[curZoneMeshPoints[pointI]] +=
1843 curZonePointDispl[pointI];
1848 twoDPointCorrector twoDCorrector(structuresMesh);
1849 twoDCorrector.correctPoints(newPoints);
1850 structuresMesh.movePoints(newPoints);
1851 structuresMesh.V00();
1852 structuresMesh.moving(
false);
1856 FatalErrorIn(args.executable())
1857 <<
"FsiFoam:Step: Negative Jacobian"
1858 << exit(FatalError);
1861 if (runTime.outputTime())
1863 volScalarField sigmaEq
1871 IOobject::AUTO_WRITE
1873 sqrt((3.0/2.0)*magSqr(dev(sigma)))
1876 Info<<
"FsiFoam:Step: Max sigmaEq = " << max(sigmaEq).value()
1893 Foam::argList &args(this->ArgList());
1894 Foam::Time &runTime(this->RunTime());
1895 dynamicFvMesh &fluidsMesh(this->FluidMesh());
1897 dimensionedScalar &nu(this->nu());
1898 dimensionedScalar &rhoFluid(this->rhoFluid());
1899 volScalarField &p(this->p());
1900 volVectorField &U(this->U());
1901 surfaceScalarField &phi(this->phi());
1906 label fluidPatchID(this->FluidPatchID());
1907 label fluidZoneID(this->FluidZoneID());
1908 label solidZoneID(this->SolidZoneID());
1910 bool feMotionSolver(this->FEMotion());
1911 bool fvMotionSolver(this->FVMotion());
1912 vectorField &accumulatedFluidInterfaceDisplacement(this->AccumulatedFluidInterfaceDisplacements());
1914 Info <<
"FsiFoam:StepFluidAlone: Checking AccumulatedFluidInterfaceDisplacementi = " << endl;
1915 Info << accumulatedFluidInterfaceDisplacement;
1917 solidTractionFvPatchVectorField &tForce(this->tForce());
1919 zoneToZoneInterpolation &interpolatorFluidSolid(this->interpFluidSolid());
1920 zoneToZoneInterpolation &interpolatorSolidFluid(this->interpSolidFluid());
1922 scalar &sumLocalContErr(this->LocalContErr());
1923 scalar &globalContErr(this->GlobalContErr());
1924 scalar &cumulativeContErr(this->CumulativeContErr());
1926 labelList &globalFaceZones(this->GlobalFaceZones());
1927 labelListList &globalToLocalFaceZonePointMap(this->GlobalToLocalFaceZonePointMap());
1931 this->ReadPISOControls();
1932 this->ReadFSIControls();
1933 word couplingScheme(this->CouplingScheme());
1935 scalar &fsiRelaxationFactor(this->FSIRelaxationFactor());
1937 Switch fsi(this->FSIEnabled());
1938 int &nCorrPISO(this->NCorrPISO());
1939 int &nNonOrthCorr(this->NNonOrthCorr());
1940 scalar &interfaceDeformationLimit(this->InterfaceDeformationLimit());
1941 scalar &outerCorrTolerance(this->OuterCorrTolerance());
1942 int &nOuterCorr(this->NOuterCorr());
1944 vectorField fluidPatchPointsDispl
1946 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
1950 vectorField fluidPatchPointsDisplOld
1952 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
1956 vectorField solidPatchPointsDispl
1958 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
1962 vectorField fsiResidual
1964 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
1968 vectorField fsiResidualOld
1970 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
1975 scalar initialFsiResidualNorm = 0;
1976 scalar fsiResidualNorm = 0;
1982 Info <<
"FsiFoam:StepFluidAlone: outerCorr = " << outerCorr << endl;
1985 Info <<
"\nFsiFoam:StepFluidAlone: Time = " << runTime.timeName()
1986 <<
", iteration: " << outerCorr << endl;
1988 if (outerCorr < 3 || couplingScheme ==
"FixedRelaxation")
1990 Info <<
"FsiFoam:StepFluidAlone: Current fsi under-relaxation factor: "
1991 << fsiRelaxationFactor << endl;
1993 fluidPatchPointsDisplOld = fluidPatchPointsDispl;
1995 fluidPatchPointsDispl += fsiRelaxationFactor*fsiResidual;
1999 if (couplingScheme ==
"Aitken")
2001 fsiRelaxationFactor =
2002 -fsiRelaxationFactor
2007 &(fsiResidual - fsiResidualOld)
2012 (fsiResidual - fsiResidualOld)
2013 &(fsiResidual - fsiResidualOld)
2018 fsiRelaxationFactor = mag(fsiRelaxationFactor);
2020 Info <<
"FsiFoam:StepFluidAlone: Current fsi under-relaxation factor (Aitken): "
2021 << fsiRelaxationFactor << endl;
2023 fluidPatchPointsDisplOld = fluidPatchPointsDispl;
2025 fluidPatchPointsDispl +=
2026 fsiRelaxationFactor*fsiResidual;
2032 const vectorField& n =
2033 fluidsMesh.boundaryMesh()[fluidPatchID].pointNormals();
2035 primitivePatchInterpolation patchInterpolator
2037 fluidsMesh.boundaryMesh()[fluidPatchID]
2040 scalarField pointDeltaCoeffs =
2041 patchInterpolator.faceToPointInterpolate
2043 fluidsMesh.boundary()[fluidPatchID].deltaCoeffs()
2053 accumulatedFluidInterfaceDisplacement
2054 + fluidPatchPointsDispl
2055 - fluidPatchPointsDisplOld
2061 Info <<
"FsiFoam:StepFluidAlone: Maximal accumulated displacement of interface points: "
2064 if(delta < interfaceDeformationLimit)
2068 Info <<
"FsiFoam:StepFluidAlone: Moving only interface...";
2070 pointField newPoints = fluidsMesh.allPoints();
2072 const labelList& meshPoints =
2073 fluidsMesh.boundaryMesh()[fluidPatchID].meshPoints();
2075 forAll (fluidPatchPointsDispl, pointI)
2080 newPoints[meshPoints[pointI]] +=
2081 fluidPatchPointsDispl[pointI]
2082 - fluidPatchPointsDisplOld[pointI];
2085 twoDPointCorrector twoDCorrector(fluidsMesh);
2087 twoDCorrector.correctPoints(newPoints);
2089 fluidsMesh.movePoints(newPoints);
2092 accumulatedFluidInterfaceDisplacement +=
2093 fluidPatchPointsDispl
2094 - fluidPatchPointsDisplOld;
2100 Info <<
"FsiFoam:StepFluidAlone: Moving the whole mesh...";
2102 pointField newPoints = fluidsMesh.allPoints();
2104 const labelList& meshPoints =
2105 fluidsMesh.boundaryMesh()[fluidPatchID].meshPoints();
2107 forAll (accumulatedFluidInterfaceDisplacement, pointI)
2111 newPoints[meshPoints[pointI]] -=
2112 accumulatedFluidInterfaceDisplacement[pointI];
2115 twoDPointCorrector twoDCorrector(fluidsMesh);
2117 twoDCorrector.correctPoints(newPoints);
2119 fluidsMesh.movePoints(newPoints);
2121 accumulatedFluidInterfaceDisplacement +=
2122 fluidPatchPointsDispl
2123 - fluidPatchPointsDisplOld;
2128 tetPointVectorField& motionU =
2129 const_cast<tetPointVectorField&
>
2131 fluidsMesh.objectRegistry::
lookupObject<tetPointVectorField>
2137 fixedValueTetPolyPatchVectorField& motionUFluidPatch =
2138 refCast<fixedValueTetPolyPatchVectorField>
2140 motionU.boundaryField()[fluidPatchID]
2143 tetPolyPatchInterpolation tppi
2145 refCast<const faceTetPolyPatch>(motionUFluidPatch.patch())
2148 motionUFluidPatch ==
2149 tppi.pointToPointInterpolate
2151 accumulatedFluidInterfaceDisplacement
2152 /runTime.deltaT().value()
2155 else if (fvMotionSolver)
2157 pointVectorField& motionU =
2158 const_cast<pointVectorField&
>
2160 fluidsMesh.objectRegistry::
lookupObject<pointVectorField>
2166 fixedValuePointPatchVectorField& motionUFluidPatch =
2167 refCast<fixedValuePointPatchVectorField>
2169 motionU.boundaryField()[fluidPatchID]
2172 motionUFluidPatch ==
2173 accumulatedFluidInterfaceDisplacement
2174 /runTime.deltaT().value();
2178 FatalErrorIn(args.executable())
2179 <<
"FsiFoam:StepFluidAlone: Problem with mesh motion solver selection"
2180 << abort(FatalError);
2183 fluidsMesh.update();
2185 accumulatedFluidInterfaceDisplacement = vector::zero;
2189 if(fluidsMesh.moving())
2192 phi -= fvc::meshPhi(U);
2197 scalar meanCoNum = 0.0;
2198 scalar velMag = 0.0;
2200 if (fluidsMesh.nInternalFaces())
2202 surfaceScalarField magPhi = mag(phi);
2204 surfaceScalarField SfUfbyDelta =
2205 fluidsMesh.surfaceInterpolation::deltaCoeffs()*magPhi;
2207 const scalar deltaT = runTime.deltaT().value();
2209 CoNum = max(SfUfbyDelta/fluidsMesh.magSf()).value()*deltaT;
2211 meanCoNum = (sum(SfUfbyDelta)/sum(fluidsMesh.magSf())).value()*deltaT;
2213 velMag = max(magPhi/fluidsMesh.magSf()).value();
2216 Info<<
"FsiFoam:StepFluidAlone: Courant Number mean: " << meanCoNum
2217 <<
" max: " << CoNum
2218 <<
" velocity magnitude: " << velMag
2225 - fvm::laplacian(nu, U)
2228 solve(UEqn == -fvc::grad(p));
2231 volScalarField rUA = 1.0/UEqn.A();
2233 Info <<
"FsiFoam:StepFluidAlone: Performing " << nCorrPISO <<
" Pressure corrections." << endl;
2236 for (
int corr=0; corr<nCorrPISO; corr++)
2239 phi = (fvc::interpolate(U) & fluidsMesh.Sf());
2241 adjustPhi(phi, U, p);
2243 for (
int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
2247 fvm::laplacian(rUA, p)
2251 pEqn.setReference(pRefCell, pRefValue);
2257 if (nonOrth == nNonOrthCorr)
2264 volScalarField contErr = fvc::div(phi);
2266 sumLocalContErr = runTime.deltaT().value()*
2267 mag(contErr)().weightedAverage(fluidsMesh.V()).value();
2269 globalContErr = runTime.deltaT().value()*
2270 contErr.weightedAverage(fluidsMesh.V()).value();
2272 cumulativeContErr += globalContErr;
2274 Info<<
"FsiFoam:StepFluidAlone: time step continuity errors : sum local = " << sumLocalContErr
2275 <<
", global = " << globalContErr
2276 <<
", cumulative = " << cumulativeContErr
2280 U -= rUA*fvc::grad(p);
2281 U.correctBoundaryConditions();
2285 Info <<
"FsiFoam:StepFluidAlone: Not Setting traction on solid patch" << endl;
2289 fsiResidualOld = fsiResidual;
2299 this->UpdateFSISurface(solidPatchPointsDispl);
2301 solidPatchPointsDispl = vector::zero;
2307 Info <<
"FsiFoam:StepFluidAlone: solidPatchPointsDispl = " << solidPatchPointsDispl << endl;
2312 fsiResidual = (solidPatchPointsDispl - fluidPatchPointsDispl);
2316 fsiResidualNorm = ::sqrt(gSum(magSqr(fsiResidual)));
2320 initialFsiResidualNorm = fsiResidualNorm;
2323 fsiResidualNorm /= initialFsiResidualNorm + SMALL;
2325 Info <<
"FsiFoam:StepFluidAlone: Current fsi residual norm: " << fsiResidualNorm << endl;
2331 (fsiResidualNorm > outerCorrTolerance)
2332 && (outerCorr < nOuterCorr)
2336 if (runTime.outputTime())
2347 Foam::argList &args(this->ArgList());
2348 Foam::Time &runTime(this->RunTime());
2349 dynamicFvMesh &fluidsMesh(this->FluidMesh());
2351 dimensionedScalar &nu(this->nu());
2352 dimensionedScalar &rhoFluid(this->rhoFluid());
2353 volScalarField &p(this->p());
2354 volVectorField &U(this->U());
2355 surfaceScalarField &phi(this->phi());
2360 label fluidPatchID(this->FluidPatchID());
2361 label fluidZoneID(this->FluidZoneID());
2362 label solidZoneID(this->SolidZoneID());
2364 bool feMotionSolver(this->FEMotion());
2365 bool fvMotionSolver(this->FVMotion());
2366 vectorField &accumulatedFluidInterfaceDisplacement(this->AccumulatedFluidInterfaceDisplacements());
2369 solidTractionFvPatchVectorField &tForce(this->tForce());
2371 zoneToZoneInterpolation &interpolatorFluidSolid(this->interpFluidSolid());
2372 zoneToZoneInterpolation &interpolatorSolidFluid(this->interpSolidFluid());
2374 scalar &sumLocalContErr(this->LocalContErr());
2375 scalar &globalContErr(this->GlobalContErr());
2376 scalar &cumulativeContErr(this->CumulativeContErr());
2378 labelList &globalFaceZones(this->GlobalFaceZones());
2379 labelListList &globalToLocalFaceZonePointMap(this->GlobalToLocalFaceZonePointMap());
2383 this->ReadPISOControls();
2384 this->ReadFSIControls();
2385 word couplingScheme(this->CouplingScheme());
2387 scalar &fsiRelaxationFactor(this->FSIRelaxationFactor());
2389 Switch fsi(this->FSIEnabled());
2390 int &nCorrPISO(this->NCorrPISO());
2391 int &nNonOrthCorr(this->NNonOrthCorr());
2392 scalar &interfaceDeformationLimit(this->InterfaceDeformationLimit());
2393 scalar &outerCorrTolerance(this->OuterCorrTolerance());
2394 int &nOuterCorr(this->NOuterCorr());
2396 vectorField fluidPatchPointsDispl
2398 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
2402 vectorField fluidPatchPointsDisplOld
2404 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
2408 vectorField solidPatchPointsDispl
2410 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
2414 vectorField fsiResidual
2416 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
2420 vectorField fsiResidualOld
2422 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
2427 scalar initialFsiResidualNorm = 0;
2428 scalar fsiResidualNorm = 0;
2434 Info <<
"FsiFoam:StepFluidNonItr: outerCorr = " << outerCorr << endl;
2437 Info <<
"FsiFoam:StepFluidNonItr: Time = " << runTime.timeName()
2438 <<
", iteration: " << outerCorr << endl;
2440 this->UpdateFSISurface(fluidPatchPointsDispl);
2445 const vectorField& n =
2446 fluidsMesh.boundaryMesh()[fluidPatchID].pointNormals();
2448 primitivePatchInterpolation patchInterpolator
2450 fluidsMesh.boundaryMesh()[fluidPatchID]
2453 scalarField pointDeltaCoeffs =
2454 patchInterpolator.faceToPointInterpolate
2456 fluidsMesh.boundary()[fluidPatchID].deltaCoeffs()
2466 accumulatedFluidInterfaceDisplacement
2467 + fluidPatchPointsDispl
2473 Info <<
"FsiFoam:StepFluidNonItr: Maximal accumulated displacement of interface points: "
2476 if(delta < interfaceDeformationLimit)
2479 Info <<
"FsiFoam:StepFluidNonItr: Moving only interface...";
2480 pointField newPoints = fluidsMesh.allPoints();
2482 const labelList& meshPoints =
2483 fluidsMesh.boundaryMesh()[fluidPatchID].meshPoints();
2485 forAll (fluidPatchPointsDispl, pointI)
2490 newPoints[meshPoints[pointI]] +=
2491 fluidPatchPointsDispl[pointI];
2494 twoDPointCorrector twoDCorrector(fluidsMesh);
2496 twoDCorrector.correctPoints(newPoints);
2498 fluidsMesh.movePoints(newPoints);
2501 accumulatedFluidInterfaceDisplacement +=
2502 fluidPatchPointsDispl;
2507 Info <<
"FsiFoam:StepFluidNonItr: Moving the whole mesh...";
2508 pointField newPoints = fluidsMesh.allPoints();
2510 const labelList& meshPoints =
2511 fluidsMesh.boundaryMesh()[fluidPatchID].meshPoints();
2513 forAll (accumulatedFluidInterfaceDisplacement, pointI)
2517 newPoints[meshPoints[pointI]] -=
2518 accumulatedFluidInterfaceDisplacement[pointI];
2521 twoDPointCorrector twoDCorrector(fluidsMesh);
2523 twoDCorrector.correctPoints(newPoints);
2525 fluidsMesh.movePoints(newPoints);
2527 accumulatedFluidInterfaceDisplacement +=
2528 fluidPatchPointsDispl;
2532 tetPointVectorField& motionU =
2533 const_cast<tetPointVectorField&
>
2535 fluidsMesh.objectRegistry::
lookupObject<tetPointVectorField>
2541 fixedValueTetPolyPatchVectorField& motionUFluidPatch =
2542 refCast<fixedValueTetPolyPatchVectorField>
2544 motionU.boundaryField()[fluidPatchID]
2547 tetPolyPatchInterpolation tppi
2549 refCast<const faceTetPolyPatch>(motionUFluidPatch.patch())
2552 motionUFluidPatch ==
2553 tppi.pointToPointInterpolate
2555 accumulatedFluidInterfaceDisplacement
2556 /runTime.deltaT().value()
2559 else if (fvMotionSolver)
2561 pointVectorField& motionU =
2562 const_cast<pointVectorField&
>
2564 fluidsMesh.objectRegistry::
lookupObject<pointVectorField>
2570 fixedValuePointPatchVectorField& motionUFluidPatch =
2571 refCast<fixedValuePointPatchVectorField>
2573 motionU.boundaryField()[fluidPatchID]
2576 motionUFluidPatch ==
2577 accumulatedFluidInterfaceDisplacement
2578 /runTime.deltaT().value();
2582 FatalErrorIn(args.executable())
2583 <<
"FsiFoam:StepFluidNonItr: Problem with mesh motion solver selection"
2584 << abort(FatalError);
2588 Info <<
"FsiFoam:StepFluidNonItr: runTime.deltaT() = "
2589 << runTime.deltaT().value() << endl;
2592 fluidsMesh.update();
2594 accumulatedFluidInterfaceDisplacement = vector::zero;
2598 if(fluidsMesh.moving())
2601 Info <<
"FsiFoam:StepFluidNonItr: Compensating for mesh movment !" << endl;
2602 phi -= fvc::meshPhi(U);
2607 scalar meanCoNum = 0.0;
2608 scalar velMag = 0.0;
2610 if (fluidsMesh.nInternalFaces())
2612 surfaceScalarField magPhi = mag(phi);
2614 surfaceScalarField SfUfbyDelta =
2615 fluidsMesh.surfaceInterpolation::deltaCoeffs()*magPhi;
2617 const scalar deltaT = runTime.deltaT().value();
2619 CoNum = max(SfUfbyDelta/fluidsMesh.magSf()).value()*deltaT;
2621 meanCoNum = (sum(SfUfbyDelta)/sum(fluidsMesh.magSf())).value()*deltaT;
2623 velMag = max(magPhi/fluidsMesh.magSf()).value();
2626 Info<<
"FsiFoam:StepFluidNonItr: Courant Number mean: " << meanCoNum
2627 <<
" max: " << CoNum
2628 <<
" velocity magnitude: " << velMag
2635 - fvm::laplacian(nu, U)
2638 solve(UEqn == -fvc::grad(p));
2641 volScalarField rUA = 1.0/UEqn.A();
2644 for (
int corr=0; corr<nCorrPISO; corr++)
2647 phi = (fvc::interpolate(U) & fluidsMesh.Sf());
2649 adjustPhi(phi, U, p);
2651 for (
int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
2655 fvm::laplacian(rUA, p)
2659 pEqn.setReference(pRefCell, pRefValue);
2664 if (nonOrth == nNonOrthCorr)
2671 volScalarField contErr = fvc::div(phi);
2673 sumLocalContErr = runTime.deltaT().value()*
2674 mag(contErr)().weightedAverage(fluidsMesh.V()).value();
2676 globalContErr = runTime.deltaT().value()*
2677 contErr.weightedAverage(fluidsMesh.V()).value();
2679 cumulativeContErr += globalContErr;
2681 Info<<
"FsiFoam:StepFluidNonItr: time step continuity errors : sum local = " << sumLocalContErr
2682 <<
", global = " << globalContErr
2683 <<
", cumulative = " << cumulativeContErr
2687 U -= rUA*fvc::grad(p);
2688 U.correctBoundaryConditions();
2696 if (runTime.outputTime())
2709 Foam::argList &args(this->ArgList());
2710 Foam::Time &runTime(this->RunTime());
2711 dynamicFvMesh &fluidsMesh(this->FluidMesh());
2713 dimensionedScalar &nu(this->nu());
2714 dimensionedScalar &rhoFluid(this->rhoFluid());
2715 volScalarField &p(this->p());
2716 volVectorField &U(this->U());
2717 surfaceScalarField &phi(this->phi());
2722 label fluidPatchID(this->FluidPatchID());
2723 label fluidZoneID(this->FluidZoneID());
2724 label solidZoneID(this->SolidZoneID());
2726 bool feMotionSolver(this->FEMotion());
2727 bool fvMotionSolver(this->FVMotion());
2728 vectorField &accumulatedFluidInterfaceDisplacement(this->AccumulatedFluidInterfaceDisplacements());
2730 Info <<
"FsiFoam:StepFluidItr: Checking AccumulatedFluidInterfaceDisplacementi = " << endl;
2731 Info << accumulatedFluidInterfaceDisplacement;
2733 solidTractionFvPatchVectorField &tForce(this->tForce());
2735 zoneToZoneInterpolation &interpolatorFluidSolid(this->interpFluidSolid());
2736 zoneToZoneInterpolation &interpolatorSolidFluid(this->interpSolidFluid());
2738 scalar &sumLocalContErr(this->LocalContErr());
2739 scalar &globalContErr(this->GlobalContErr());
2740 scalar &cumulativeContErr(this->CumulativeContErr());
2742 labelList &globalFaceZones(this->GlobalFaceZones());
2743 labelListList &globalToLocalFaceZonePointMap(this->GlobalToLocalFaceZonePointMap());
2747 this->ReadPISOControls();
2748 this->ReadFSIControls();
2749 word couplingScheme(this->CouplingScheme());
2751 scalar &fsiRelaxationFactor(this->FSIRelaxationFactor());
2753 Switch fsi(this->FSIEnabled());
2754 int &nCorrPISO(this->NCorrPISO());
2755 int &nNonOrthCorr(this->NNonOrthCorr());
2756 scalar &interfaceDeformationLimit(this->InterfaceDeformationLimit());
2757 scalar &outerCorrTolerance(this->OuterCorrTolerance());
2758 int &nOuterCorr(this->NOuterCorr());
2760 vectorField fluidPatchPointsDispl
2762 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
2766 vectorField fluidPatchPointsDisplOld
2768 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
2772 vectorField solidPatchPointsDispl
2774 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
2778 vectorField fsiResidual
2780 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
2784 vectorField fsiResidualOld
2786 fluidsMesh.boundaryMesh()[fluidPatchID].nPoints(),
2791 scalar initialFsiResidualNorm = 0;
2792 scalar fsiResidualNorm = 0;
2798 Info <<
"FsiFoam:StepFluidItr: outerCorr = " << outerCorr << endl;
2801 Info <<
"\nFsiFoam:StepFluidItr: Time = " << runTime.timeName()
2802 <<
", iteration: " << outerCorr << endl;
2804 if (outerCorr < 3 || couplingScheme ==
"FixedRelaxation")
2806 Info <<
"FsiFoam:StepFluidItr: Current fsi under-relaxation factor: "
2807 << fsiRelaxationFactor << endl;
2809 fluidPatchPointsDisplOld = fluidPatchPointsDispl;
2811 fluidPatchPointsDispl += fsiRelaxationFactor*fsiResidual;
2815 if (couplingScheme ==
"Aitken")
2817 fsiRelaxationFactor =
2818 -fsiRelaxationFactor
2823 &(fsiResidual - fsiResidualOld)
2828 (fsiResidual - fsiResidualOld)
2829 &(fsiResidual - fsiResidualOld)
2834 fsiRelaxationFactor = mag(fsiRelaxationFactor);
2836 Info <<
"FsiFoam:StepFluidItr: Current fsi under-relaxation factor (Aitken): "
2837 << fsiRelaxationFactor << endl;
2839 fluidPatchPointsDisplOld = fluidPatchPointsDispl;
2841 fluidPatchPointsDispl +=
2842 fsiRelaxationFactor*fsiResidual;
2848 const vectorField& n =
2849 fluidsMesh.boundaryMesh()[fluidPatchID].pointNormals();
2851 primitivePatchInterpolation patchInterpolator
2853 fluidsMesh.boundaryMesh()[fluidPatchID]
2856 scalarField pointDeltaCoeffs =
2857 patchInterpolator.faceToPointInterpolate
2859 fluidsMesh.boundary()[fluidPatchID].deltaCoeffs()
2869 accumulatedFluidInterfaceDisplacement
2870 + fluidPatchPointsDispl
2871 - fluidPatchPointsDisplOld
2877 Info <<
"FsiFoam:StepFluidItr: Maximal accumulated displacement of interface points: "
2880 if(delta < interfaceDeformationLimit)
2884 Info <<
"FsiFoam:StepFluidItr: Moving only interface...";
2886 pointField newPoints = fluidsMesh.allPoints();
2888 const labelList& meshPoints =
2889 fluidsMesh.boundaryMesh()[fluidPatchID].meshPoints();
2891 forAll (fluidPatchPointsDispl, pointI)
2896 newPoints[meshPoints[pointI]] +=
2897 fluidPatchPointsDispl[pointI]
2898 - fluidPatchPointsDisplOld[pointI];
2901 twoDPointCorrector twoDCorrector(fluidsMesh);
2903 twoDCorrector.correctPoints(newPoints);
2905 fluidsMesh.movePoints(newPoints);
2908 accumulatedFluidInterfaceDisplacement +=
2909 fluidPatchPointsDispl
2910 - fluidPatchPointsDisplOld;
2916 Info <<
"FsiFoam:StepFluidItr: Moving the whole mesh...";
2918 pointField newPoints = fluidsMesh.allPoints();
2920 const labelList& meshPoints =
2921 fluidsMesh.boundaryMesh()[fluidPatchID].meshPoints();
2923 forAll (accumulatedFluidInterfaceDisplacement, pointI)
2927 newPoints[meshPoints[pointI]] -=
2928 accumulatedFluidInterfaceDisplacement[pointI];
2931 twoDPointCorrector twoDCorrector(fluidsMesh);
2933 twoDCorrector.correctPoints(newPoints);
2935 fluidsMesh.movePoints(newPoints);
2937 accumulatedFluidInterfaceDisplacement +=
2938 fluidPatchPointsDispl
2939 - fluidPatchPointsDisplOld;
2944 tetPointVectorField& motionU =
2945 const_cast<tetPointVectorField&
>
2947 fluidsMesh.objectRegistry::
lookupObject<tetPointVectorField>
2953 fixedValueTetPolyPatchVectorField& motionUFluidPatch =
2954 refCast<fixedValueTetPolyPatchVectorField>
2956 motionU.boundaryField()[fluidPatchID]
2959 tetPolyPatchInterpolation tppi
2961 refCast<const faceTetPolyPatch>(motionUFluidPatch.patch())
2964 motionUFluidPatch ==
2965 tppi.pointToPointInterpolate
2967 accumulatedFluidInterfaceDisplacement
2968 /runTime.deltaT().value()
2971 else if (fvMotionSolver)
2973 pointVectorField& motionU =
2974 const_cast<pointVectorField&
>
2976 fluidsMesh.objectRegistry::
lookupObject<pointVectorField>
2982 fixedValuePointPatchVectorField& motionUFluidPatch =
2983 refCast<fixedValuePointPatchVectorField>
2985 motionU.boundaryField()[fluidPatchID]
2988 motionUFluidPatch ==
2989 accumulatedFluidInterfaceDisplacement
2990 /runTime.deltaT().value();
2994 FatalErrorIn(args.executable())
2995 <<
"FsiFoam:StepFluidItr: Problem with mesh motion solver selection"
2996 << abort(FatalError);
2999 fluidsMesh.update();
3001 accumulatedFluidInterfaceDisplacement = vector::zero;
3005 if(fluidsMesh.moving())
3008 phi -= fvc::meshPhi(U);
3013 scalar meanCoNum = 0.0;
3014 scalar velMag = 0.0;
3016 if (fluidsMesh.nInternalFaces())
3018 surfaceScalarField magPhi = mag(phi);
3020 surfaceScalarField SfUfbyDelta =
3021 fluidsMesh.surfaceInterpolation::deltaCoeffs()*magPhi;
3023 const scalar deltaT = runTime.deltaT().value();
3025 CoNum = max(SfUfbyDelta/fluidsMesh.magSf()).value()*deltaT;
3027 meanCoNum = (sum(SfUfbyDelta)/sum(fluidsMesh.magSf())).value()*deltaT;
3029 velMag = max(magPhi/fluidsMesh.magSf()).value();
3032 Info<<
"FsiFoam:StepFluidItr: Courant Number mean: " << meanCoNum
3033 <<
" max: " << CoNum
3034 <<
" velocity magnitude: " << velMag
3041 - fvm::laplacian(nu, U)
3044 solve(UEqn == -fvc::grad(p));
3047 volScalarField rUA = 1.0/UEqn.A();
3049 Info <<
"FsiFoam:StepFluidItr: Performing " << nCorrPISO <<
" Pressure corrections." << endl;
3052 for (
int corr=0; corr<nCorrPISO; corr++)
3055 phi = (fvc::interpolate(U) & fluidsMesh.Sf());
3057 adjustPhi(phi, U, p);
3059 for (
int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
3063 fvm::laplacian(rUA, p)
3067 pEqn.setReference(pRefCell, pRefValue);
3073 if (nonOrth == nNonOrthCorr)
3080 volScalarField contErr = fvc::div(phi);
3082 sumLocalContErr = runTime.deltaT().value()*
3083 mag(contErr)().weightedAverage(fluidsMesh.V()).value();
3085 globalContErr = runTime.deltaT().value()*
3086 contErr.weightedAverage(fluidsMesh.V()).value();
3088 cumulativeContErr += globalContErr;
3090 Info<<
"FsiFoam:StepFluidItr: time step continuity errors : sum local = " << sumLocalContErr
3091 <<
", global = " << globalContErr
3092 <<
", cumulative = " << cumulativeContErr
3096 U -= rUA*fvc::grad(p);
3097 U.correctBoundaryConditions();
3101 Info <<
"FsiFoam:StepFluidItr: Setting tractionis on solid patch" << endl;
3105 fsiResidualOld = fsiResidual;
3106 this->UpdateFSISurface(solidPatchPointsDispl);
3107 Info <<
"FsiFoam:StepFluidItr: solidPatchPointsDispl = " << solidPatchPointsDispl << endl;
3109 fsiResidual = (solidPatchPointsDispl - fluidPatchPointsDispl);
3110 fsiResidualNorm = ::sqrt(gSum(magSqr(fsiResidual)));
3114 initialFsiResidualNorm = fsiResidualNorm;
3117 fsiResidualNorm /= initialFsiResidualNorm + SMALL;
3119 Info <<
"FsiFoam:StepFluidItr: Current fsi residual norm: " << fsiResidualNorm << endl;
3125 (fsiResidualNorm > outerCorrTolerance)
3126 && (outerCorr < nOuterCorr)
3130 if (runTime.outputTime())
3140 Foam::Time &runTime(this->RunTime());
3141 fvMesh &structuresMesh(this->StructuresMesh());
3142 volSymmTensorField &sigma(this->sigma());
3143 volScalarField sigmaEq
3151 IOobject::AUTO_WRITE
3153 sqrt((3.0/2.0)*magSqr(dev(sigma)))
3156 Info<<
"FsiFoam:Dump: Max sigmaEq = " << max(sigmaEq).value()
3172 inComm = COM_get_default_communicator();
3175 MPI_Comm_rank(inComm, &rank);
3176 MPI_Comm_size(inComm, &size);
3177 Info <<
"FsiFoam:Load:Rank #"
3179 <<
" on communicator "
3184 Info <<
"FsiFoam:Load:Rank #"
3186 <<
" Loading FsiFoamModule with name "
3194 COM_new_window(name, MPI_COMM_NULL);
3199 std::string global_name(name+
".global");
3200 COM_new_dataitem(global_name.c_str(),
'w',COM_VOID,1,
"");
3201 COM_set_object(global_name.c_str(),0,module_pointer);
3205 std::vector<COM_Type> types(13,COM_INT);
3207 types[0] = COM_RAWDATA;
3208 types[2] = COM_VOID;
3209 COM_set_member_function( (name+
".InitFoam").c_str(),
3211 global_name.c_str(),
"biii", &types[0]);
3213 COM_set_member_function( (name+
".RunFoam").c_str(),
3215 global_name.c_str(),
"b", &types[0]);
3218 COM_set_member_function( (name+
".StepFoam").c_str(),
3220 global_name.c_str(),
"b", &types[0]);
3222 COM_set_member_function( (name+
".StepFluid").c_str(),
3224 global_name.c_str(),
"b", &types[0]);
3227 COM_new_dataitem( (name+
".nproc").c_str(),
'w', COM_INT, 1,
"");
3228 COM_set_size( (name+
".nproc").c_str(), 0, 1);
3229 COM_set_array( (name+
".nproc").c_str(), 0, &(module_pointer->
nproc));
3238 COM_window_init_done(name);
3245 char** argv = (
char**)(pargv);
3246 verbosity = *verbIn;
3257 Initialize(argc, argv);
3261 Solution().Meta().AddField(
"time",
's', 1, 8,
"s");
3262 Solution().Meta().AddField(
"endTime",
's', 1, 8,
"s");
3263 Solution().Meta().AddField(
"initStatus",
's', 1, 4,
"");
3264 Solution().Meta().AddField(
"runStatus",
's', 1, 4,
"");
3265 Solution().Meta().AddField(
"dt",
's', 1, 8,
"s");
3266 Solution().Meta().AddField(
"solidDisplacement",
'n', 3, 8,
"m");
3267 Solution().Meta().AddField(
"pressure",
'c', 1, 8,
"Pa");
3268 Solution().Meta().AddField(
"traction",
'c', 3, 8,
"N");
3271 Mesh().nc.init(numPointsSurface, &surfaceCoordinates[0]);
3274 Mesh().con.AddElements(numElementsSurface, 4, surfaceConnectivity);
3281 if (numPointsSurface==0 && numElementsSurface==0)
3282 std::cout <<
"Process " << Rank()
3283 <<
" has no share on interface data ... "
3291 time.resize(1, -1.0);
3292 endTime.resize(1, -1.0);
3295 initStatus.resize(1, -1000);
3296 runStatus.resize(1, -1000);
3298 surfacePressure.resize(numElementsSurface, -1);
3299 surfaceTraction.resize(3*numElementsSurface, -1);
3300 solidDisplacement.resize(3*numPointsSurface, 0.);
3304 Solution().SetFieldBuffer(
"initStatus", initStatus);
3305 Solution().SetFieldBuffer(
"runStatus", runStatus);
3306 Solution().SetFieldBuffer(
"time", time);
3307 Solution().SetFieldBuffer(
"endTime", endTime);
3308 Solution().SetFieldBuffer(
"pressure", surfacePressure);
3309 Solution().SetFieldBuffer(
"traction", surfaceTraction);
3310 Solution().SetFieldBuffer(
"solidDisplacement", solidDisplacement);
3318 int paneId = rank + 200;
3322 SolverUtils::CreateDataItemsFromSolution(my_window_name.c_str(),Solution());
3323 if (numPointsSurface!=0 && numElementsSurface!=0)
3324 SolverUtils::AgentToPane(my_window_name.c_str(),paneId,*
this);
3327 COM_window_init_done(my_window_name.c_str());
3330 std::cout <<
"Rank " << Rank() <<
" finished " << std::endl;
3342 std::cout <<
"FsiFoam:Unload: Unloading FsiFoamModule with name " << name
3343 <<
"." << std::endl;
3345 std::string global_name(name+
".global");
3346 COM_get_object(global_name.c_str(),0,&module_pointer);
3347 COM_assertion_msg( module_pointer->validate_object()==0,
"Invalid object");
3348 delete module_pointer;
3349 COM_delete_window(std::string(name));
3358 Foam::Time &runTime(RunTime());
3360 Info <<
"\nFsiFoam:RunFoam: Starting time loop\n" << endl;
3362 while(!runTime.end()){
3363 Info <<
"FsiFoam:RunFoam: Time = " << runTime.timeName() << nl << endl;
3365 Info<<
"ExecutionTime = " << runTime.elapsedCpuTime() <<
" s"
3366 <<
" ClockTime = " << runTime.elapsedClockTime() <<
" s"
3368 if (runTime.outputTime())
3372 Info<<
"FsiFoam:RunFoam: End\n" << endl;
3384 Foam::Time &runTime(RunTime());
3386 Info <<
"\nFsiFoam:StepFoam: Stepping time loop\n" << endl;
3390 Info <<
"FsiFoam:StepFoam: Time = " << runTime.timeName() << nl << endl;
3392 Info<<
"ExecutionTime = " << runTime.elapsedCpuTime() <<
" s"
3393 <<
" ClockTime = " << runTime.elapsedClockTime() <<
" s"
3395 if (runTime.outputTime())
3400 UpdateFSISurfaceData();
3401 UpdateFSISurfaceMesh();
3402 Info <<
"FsiFoam:StepFoam: End of time step." << endl;
3416 Info<<
"End\n" << endl;
3428 std::stringstream ss;
3429 std::string tmpFname;
3430 ofstream surfDmpFile;
3431 dynamicFvMesh &fluidsMesh(this->FluidMesh());
3432 pointField foamCoords = fluidsMesh.allPoints();
3434 int *setsProb = NULL;
3435 int setsProb_handle;
3436 int *probProcId, *probNdeId;
3437 bool recordProb =
false;
3438 std::string dataItemName(my_window_name+
".setsProb");
3439 setsProb_handle = COM_get_dataitem_handle(dataItemName.c_str());
3440 if (setsProb_handle) {
3441 COM_get_array(dataItemName.c_str(), 0, &setsProb);
3443 dataItemName = my_window_name+
".probProcId";
3444 COM_get_array(dataItemName.c_str(), 0, &probProcId);
3445 dataItemName = my_window_name+
".probNdeId";
3446 COM_get_array(dataItemName.c_str(), 0, &probNdeId);
3447 recordProb = (*probProcId==rank) && (*probNdeId>=0 && *probNdeId<numPointsSurface);
3448 std::cout <<
"****** Rank " << rank <<
" probe state = " << recordProb << std::endl;
3452 Foam::Time &runTime(RunTime());
3453 Info <<
"FsiFoam:StepFluid: Stepping fluid solver..." << endl;
3457 Info <<
"FsiFoam:StepFluid: Time = " << runTime.timeName() << endl;
3462 Info<<
"FsiFoam:StepFluid: ExecutionTime = " << runTime.elapsedCpuTime() <<
" s"
3463 <<
" ClockTime = " << runTime.elapsedClockTime() <<
" s"
3465 if (runTime.outputTime())
3470 UpdateFSISurfaceData();
3471 UpdateFSISurfaceMesh();
3482 tmpFname = ss.str();
3483 surfDmpFile.open(tmpFname.c_str(), std::ios::app);
3490 surfDmpFile << runTime.timeName() <<
" "
3491 << surfaceCoordinates[i*3] <<
" "
3492 << surfaceCoordinates[i*3+1] <<
" "
3493 << surfaceCoordinates[i*3+2] <<
"\n";
3495 surfDmpFile.close();
3500 Info<<
"FsiFoam:StepFluid: End\n" << endl;
3514 dynamicFvMesh &fluidsMesh(this->FluidMesh());
3515 numPointsSurface = fluidsMesh.boundaryMesh()[fluidPatchID].nPoints();
3519 const faceList& faces = fluidsMesh.faces();
3520 const labelList& owner = fluidsMesh.faceOwner();
3521 const polyBoundaryMesh& boundaryMesh = fluidsMesh.boundaryMesh();
3522 const label start = boundaryMesh[fluidPatchID].start();
3523 const label end = start + boundaryMesh[fluidPatchID].size();
3524 numElementsSurface = end - start;
3527 const pointField points = fluidsMesh.points();
3531 for (label faceI = start; faceI < end; ++faceI) {
3532 const labelList& vrtList = faces[faceI];
3533 forAll(vrtList, i) {
3534 const label& vertex = vrtList[i];
3537 if (!surfaceNodeMap[vertex]) {
3538 surfaceNodeMap[vertex] = nodeNumber;
3539 interfaceToFoamNodeMap[nodeNumber] = vertex;
3542 surfaceCoordinates.push_back(points[vertex].x());
3543 surfaceCoordinates.push_back(points[vertex].y());
3544 surfaceCoordinates.push_back(points[vertex].z());
3547 surfaceConnectivity.push_back(vertex);
3552 const labelList& meshPoints =
3553 fluidsMesh.boundaryMesh()[fluidPatchID].meshPoints();
3554 for (
int i=0; i<numPointsSurface; ++i) {
3555 foamGlobalToPatchNodeMap[meshPoints[i]] = i;
3560 for (
unsigned int i=0; i<surfaceConnectivity.size(); ++i) {
3561 surfaceConnectivity[i] = surfaceNodeMap[surfaceConnectivity[i]];
3567 dynamicFvMesh &fluidsMesh(this->FluidMesh());
3568 pointField foamCoords = fluidsMesh.allPoints();
3570 for (
int i=0; i<numPointsSurface; ++i) {
3571 int vertex = interfaceToFoamNodeMap[i+1];
3572 surfaceCoordinates[3*i] = foamCoords[vertex].x();
3573 surfaceCoordinates[3*i+1] = foamCoords[vertex].y();
3574 surfaceCoordinates[3*i+2] = foamCoords[vertex].z();
3579 Foam::Time &runTime(this->RunTime());
3580 time[0] = runTime.value();
3581 endTime[0] = runTime.endTime().value();
3586 Info <<
"FsiFoam:UpdateFSISurface: Reporting solid displacements to the fluid solver" << endl;
3592 for(
int i=0; i<numPointsSurface; ++i) {
3593 solidDispl[foamGlobalToPatchNodeMap[interfaceToFoamNodeMap[i+1]]].x() =
3594 solidDisplacement[3*i];
3595 solidDispl[foamGlobalToPatchNodeMap[interfaceToFoamNodeMap[i+1]]].y() =
3596 solidDisplacement[3*i+1];
3597 solidDispl[foamGlobalToPatchNodeMap[interfaceToFoamNodeMap[i+1]]].z() =
3598 solidDisplacement[3*i+2];
3611 double currTime((this->RunTime()).value());
3612 Info <<
"FsiFoam:UpdateFSISurface: Reporting surface loads to the solid solver " << endl;
3617 dimensionedScalar &rhoFluid(this->rhoFluid());
3618 volScalarField &p(this->p());
3620 scalarField foamSurfacePressure = rhoFluid.value()*p.boundaryField()[fluidPatchID];
3622 for(
int i=0; i<numElementsSurface; ++i) {
3623 surfacePressure[i] = foamSurfacePressure[i];
3629 dimensionedScalar &nu(this->nu());
3630 volVectorField &U(this->U());
3643 dynamicFvMesh &fluidsMesh(this->FluidMesh());
3644 vectorField foamSurfaceTraction = -rhoFluid.value()*nu.value()
3645 *U.boundaryField()[fluidPatchID].snGrad()
3646 + rhoFluid.value()*p.boundaryField()[fluidPatchID]
3647 *fluidsMesh.boundary()[fluidPatchID].nf();
3651 if (currTime > -0.1) {
3652 for(
int i=0; i<numElementsSurface; ++i) {
3653 surfaceTraction[3*i] = foamSurfaceTraction[i].x();
3654 surfaceTraction[3*i+1] = foamSurfaceTraction[i].y();
3655 surfaceTraction[3*i+2] = foamSurfaceTraction[i].z();
3658 for(
int i=0; i<numElementsSurface; ++i) {
3659 surfaceTraction[3*i] = 0.0;
3660 surfaceTraction[3*i+1] = 0.0;
3661 surfaceTraction[3*i+2] = 0.0;
3679 MPI_Comm my_window_comm
Tracks this window name.
void UpdateFSISurfaceData()
Update the data registered on the FSI surface.
void StepFoam()
the OpenFOAM stepping
void OpenFoamFSIPar_unload_module(const char *name)
C/C++ bindings to unload IcoFoamModule.
void InitFoam(int *pargc, void **pargv, int *verbIn)
function to register through IMPACT
int UpdateFSISurface(Foam::vectorField &solidPatchPointsDispl)
Update the nodal coordinates of the IMAPCT and OpenFoam FSI surfaces from the IMPACT displacement dat...
void UpdateTime()
Update the time control data registered with OpenFOAM i.e.
static void Load(const std::string &name)
"Loads" IcoFoamModule
static void Unload(const std::string &name)
Unloads the IcoFoamModule.
void RunFoam()
the OpenFOAM main
int Initialize(int argc, char *argv[])
int rank
Tracks window's communicator.
std::string my_window_name
void StepFluid()
the OpenFOAM stepping fluid alone
void UpdateFSISurfaceMesh()
Update of the surface mesh data coordinates.
int CreateInterZoneInterpolators()
void CreateFSISurfaceMesh()
Initialization of the surface mesh data structures from the OpenFOAM mesh data structures.
int InitTransportProperties()
int ReadCouplingProperties()
int CreateStructuresFields()
int FindGlobalFaceZones()
void OpenFoamFSIPar_load_module(const char *name)
C/C++ bindings to load IcoFoamModule.