DAOutputForceCoupling.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2 
3  DAFoam : Discrete Adjoint with OpenFOAM
4  Version : v4
5 
6 \*---------------------------------------------------------------------------*/
7 
9 
10 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
11 
12 namespace Foam
13 {
14 
15 defineTypeNameAndDebug(DAOutputForceCoupling, 0);
16 addToRunTimeSelectionTable(DAOutput, DAOutputForceCoupling, dictionary);
17 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
18 
20  const word outputName,
21  const word outputType,
22  fvMesh& mesh,
23  const DAOption& daOption,
24  DAModel& daModel,
25  const DAIndex& daIndex,
26  DAResidual& daResidual,
27  UPtrList<DAFunction>& daFunctionList)
28  : DAOutput(
29  outputName,
30  outputType,
31  mesh,
32  daOption,
33  daModel,
34  daIndex,
35  daResidual,
36  daFunctionList)
37 {
38  daOption_.getAllOptions().subDict("outputInfo").subDict(outputName_).readEntry("patches", patches_);
39  pRef_ = daOption_.getAllOptions().subDict("outputInfo").subDict(outputName_).getScalar("pRef");
40  // NOTE: always sort the patch because the order of the patch element matters in FSI coupling
41  sort(patches_);
42 
43  // calculate how many nodal points are in the above patches
44  // NOTE: we will have duplicated points for parallel cases
45  size_ = 0;
46  const pointMesh& pMesh = pointMesh::New(mesh_);
47  const pointBoundaryMesh& boundaryMesh = pMesh.boundary();
48  forAll(patches_, cI)
49  {
50  // Get number of points in patch
51  word patchName = patches_[cI];
52  label patchIPoints = boundaryMesh.findPatchID(patchName);
53  size_ += boundaryMesh[patchIPoints].size();
54  }
55  // we have x, y, z coords for each point
56  size_ *= 3;
57 }
58 
59 void DAOutputForceCoupling::run(scalarList& output)
60 {
61  /*
62  Description:
63  Assign output based on OF fields
64  */
65 
66  scalarList fX(size_ / 3);
67  scalarList fY(size_ / 3);
68  scalarList fZ(size_ / 3);
69 
70  // Initialize surface field for face-centered forces
71  volVectorField volumeForceField(
72  IOobject(
73  "volumeForceField",
74  mesh_.time().timeName(),
75  mesh_,
76  IOobject::NO_READ,
77  IOobject::NO_WRITE),
78  mesh_,
79  dimensionedVector("surfaceForce", dimensionSet(1, 1, -2, 0, 0, 0, 0), vector::zero),
80  "fixedValue");
81 
82  // this code is pulled from:
83  // src/functionObjects/forces/forces.C
84  // modified slightly
85  vector force(vector::zero);
86 
87  const objectRegistry& db = mesh_.thisDb();
88  const volScalarField& p = db.lookupObject<volScalarField>("p");
89 
90  const surfaceVectorField::Boundary& Sfb = mesh_.Sf().boundaryField();
91 
93  tmp<volSymmTensorField> tdevRhoReff = daTurb.devRhoReff();
94  const volSymmTensorField::Boundary& devRhoReffb = tdevRhoReff().boundaryField();
95 
96  const pointMesh& pMesh = pointMesh::New(mesh_);
97  const pointBoundaryMesh& boundaryMesh = pMesh.boundary();
98 
99  // iterate over patches and extract boundary surface forces
100  forAll(patches_, cI)
101  {
102  // get the patch id label
103  label patchI = mesh_.boundaryMesh().findPatchID(patches_[cI]);
104  // create a shorter handle for the boundary patch
105  const fvPatch& patch = mesh_.boundary()[patchI];
106  // normal force
107  vectorField fN(Sfb[patchI] * (p.boundaryField()[patchI] - pRef_));
108  // tangential force
109  vectorField fT(Sfb[patchI] & devRhoReffb[patchI]);
110  // sum them up
111  forAll(patch, faceI)
112  {
113  force.x() = fN[faceI].x() + fT[faceI].x();
114  force.y() = fN[faceI].y() + fT[faceI].y();
115  force.z() = fN[faceI].z() + fT[faceI].z();
116  volumeForceField.boundaryFieldRef()[patchI][faceI] = force;
117  }
118  }
119  volumeForceField.write();
120 
121  // The above volumeForceField is face-centered, we need to interpolate it to point-centered
122  pointField meshPoints = mesh_.points();
123 
124  vector nodeForce(vector::zero);
125 
126  label patchStart = 0;
127  forAll(patches_, cI)
128  {
129  // get the patch id label
130  label patchI = mesh_.boundaryMesh().findPatchID(patches_[cI]);
131  label patchIPoints = boundaryMesh.findPatchID(patches_[cI]);
132 
133  label nPointsPatch = boundaryMesh[patchIPoints].size();
134  List<scalar> fXTemp(nPointsPatch);
135  List<scalar> fYTemp(nPointsPatch);
136  List<scalar> fZTemp(nPointsPatch);
137  List<label> pointListTemp(nPointsPatch);
138  pointListTemp = -1;
139 
140  label pointCounter = 0;
141  // Loop over Faces
142  forAll(mesh_.boundaryMesh()[patchI], faceI)
143  {
144  // Get number of points
145  const label nPoints = mesh_.boundaryMesh()[patchI][faceI].size();
146 
147  // Divide force to nodes
148  nodeForce = volumeForceField.boundaryFieldRef()[patchI][faceI] / nPoints;
149 
150  forAll(mesh_.boundaryMesh()[patchI][faceI], pointI)
151  {
152  // this is the index that corresponds to meshPoints, which contains both volume and surface points
153  // so we can't directly reuse this index because we want to have only surface points
154  label faceIPointIndexI = mesh_.boundaryMesh()[patchI][faceI][pointI];
155 
156  // Loop over pointListTemp array to check if this node is already included in this patch
157  bool found = false;
158  label iPoint = -1;
159  for (label i = 0; i < pointCounter; i++)
160  {
161  if (faceIPointIndexI == pointListTemp[i])
162  {
163  found = true;
164  iPoint = i;
165  break;
166  }
167  }
168 
169  // If node is already included, add value to its entry
170  if (found)
171  {
172  // Add Force
173  fXTemp[iPoint] += nodeForce[0];
174  fYTemp[iPoint] += nodeForce[1];
175  fZTemp[iPoint] += nodeForce[2];
176  }
177  // If node is not already included, add it as the newest point and add global index mapping
178  else
179  {
180  // Add Force
181  fXTemp[pointCounter] = nodeForce[0];
182  fYTemp[pointCounter] = nodeForce[1];
183  fZTemp[pointCounter] = nodeForce[2];
184 
185  // Add to Node Order Array
186  pointListTemp[pointCounter] = faceIPointIndexI;
187 
188  // Increment counter
189  pointCounter += 1;
190  }
191  }
192  }
193 
194  // Sort Patch Indices and Insert into Global Arrays
195  SortableList<label> pointListSort(pointListTemp);
196  forAll(pointListSort.indices(), indexI)
197  {
198  fX[patchStart + indexI] = fXTemp[pointListSort.indices()[indexI]];
199  fY[patchStart + indexI] = fYTemp[pointListSort.indices()[indexI]];
200  fZ[patchStart + indexI] = fZTemp[pointListSort.indices()[indexI]];
201  }
202 
203  // Increment Patch Start Index
204  patchStart += nPointsPatch;
205  }
206 
207  label counterI = 0;
208  forAll(fX, idxI)
209  {
210  output[counterI] = fX[idxI];
211  output[counterI + 1] = fY[idxI];
212  output[counterI + 2] = fZ[idxI];
213  counterI += 3;
214  }
215 }
216 
217 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
218 
219 } // End namespace Foam
220 
221 // ************************************************************************* //
DAOutputForceCoupling.H
Foam::DAOption
Definition: DAOption.H:29
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(DAFunction, DAFunctionForce, dictionary)
Foam::DAOutputForceCoupling::run
virtual void run(scalarList &output)
Definition: DAOutputForceCoupling.C:59
Foam::DAOption::getAllOptions
const dictionary & getAllOptions() const
return a reference of allOptions_ dictionary
Definition: DAOption.H:56
mesh
fvMesh & mesh
Definition: createRefsHeatTransfer.H:4
Foam::DAOutput::outputName_
const word outputName_
name of the output
Definition: DAOutput.H:44
Foam::DAOutput::daModel_
DAModel & daModel_
DAIndex object.
Definition: DAOutput.H:56
Foam::DAIndex
Definition: DAIndex.H:32
p
volScalarField & p
Definition: createRefsPimpleDyM.H:6
Foam::DAOutput
Definition: DAOutput.H:32
Foam::DAModel
Definition: DAModel.H:57
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(DAFunction, 0)
Foam::DAOutput::daOption_
const DAOption & daOption_
DAOption object.
Definition: DAOutput.H:53
Foam
Definition: checkGeometry.C:32
Foam::DATurbulenceModel::devRhoReff
tmp< volSymmTensorField > devRhoReff() const
dev terms
Definition: DATurbulenceModel.C:371
forAll
forAll(nuTilda1, cellI)
Definition: nuTilda1EqnIrkPimple.H:19
Foam::DAResidual
Definition: DAResidual.H:36
Foam::DATurbulenceModel
Definition: DATurbulenceModel.H:52
Foam::DAOutputForceCoupling::size_
label size_
the total face number for all the patches_ owned by this processor
Definition: DAOutputForceCoupling.H:37
Foam::DAOutputForceCoupling::pRef_
scalar pRef_
the reference pressure
Definition: DAOutputForceCoupling.H:40
Foam::DAModel::getDATurbulenceModel
const DATurbulenceModel & getDATurbulenceModel() const
get a reference to DATurbulenceModel
Definition: DAModel.C:176
Foam::DAOutputForceCoupling::DAOutputForceCoupling
DAOutputForceCoupling(const word outputName, const word outputType, fvMesh &mesh, const DAOption &daOption, DAModel &daModel, const DAIndex &daIndex, DAResidual &daResidual, UPtrList< DAFunction > &daFunctionList)
Definition: DAOutputForceCoupling.C:19
Foam::DAOutputForceCoupling::patches_
wordList patches_
list of patch names for the thermal var
Definition: DAOutputForceCoupling.H:34
Foam::DAOutput::mesh_
fvMesh & mesh_
fvMesh
Definition: DAOutput.H:50