Memosa-FVM  0.2
FlowModelInterior.h
Go to the documentation of this file.
1 // This file os part of FVM
2 // Copyright (c) 2012 FVM Authors
3 // See LICENSE file for terms.
4 
5 #ifndef _FLOWMODELINTERIOR_H_
6 #define _FLOWMODELINTERIOR_H_
7 
9  const StorageSite& faces,
10  MultiFieldMatrix& mfmatrix,
11  const MultiField& xField, MultiField& rField,
12  const bool isSymmetry=false)
13 {
14  const StorageSite& cells = mesh.getCells();
15  const int nCellsInterior = cells.getSelfCount();
16 
17  MultiField::ArrayIndex pIndex(&_flowFields.pressure,&cells);
18  MultiField::ArrayIndex vIndex(&_flowFields.velocity,&cells);
19 
20  const VectorT3Array& faceArea =
21  dynamic_cast<const VectorT3Array&>(_geomFields.area[faces]);
22 
23  const TArray& cellVolume =
24  dynamic_cast<const TArray&>(_geomFields.volume[cells]);
25 
26  const TArray& faceAreaMag =
27  dynamic_cast<const TArray&>(_geomFields.areaMag[faces]);
28 
29  const VectorT3Array& cellCentroid =
30  dynamic_cast<const VectorT3Array&>(_geomFields.coordinate[cells]);
31 
32  const CRConnectivity& faceCells = mesh.getFaceCells(faces);
33 
34  PPMatrix& ppMatrix =
35  dynamic_cast<PPMatrix&>(mfmatrix.getMatrix(pIndex,pIndex));
36 
37  const VVDiagArray& momAp = dynamic_cast<const VVDiagArray&>((*_momApField)[cells]);
38 
39  const VectorT3Array& V = dynamic_cast<const VectorT3Array&>(_flowFields.velocity[cells]);
40  const VectorT3Array& Vprev = dynamic_cast<const VectorT3Array&>((*_previousVelocity)[cells]);
41 
42  const TArray& p = dynamic_cast<const TArray&>(_flowFields.pressure[cells]);
43  const PGradArray& pGrad = dynamic_cast<const PGradArray&>(_flowFields.pressureGradient[cells]);
44 
45  const TArray& rho = dynamic_cast<TArray&>(_flowFields.density[cells]);
46 
47  PPAssembler& ppAssembler = ppMatrix.getPairWiseAssembler(faceCells);
48  PPDiagArray& ppDiag = ppMatrix.getDiag();
49 
50  TArray& rCell = dynamic_cast<TArray&>(rField[pIndex]);
51  TArray& massFlux = dynamic_cast<TArray&>(_flowFields.massFlux[faces]);
52 
53  const T momURF(_options["momentumURF"]);
54  const T OneMinusmomURF(T(1.0)-momURF);
55 
56  const IntArray& ibType = dynamic_cast<const IntArray&>(_geomFields.ibType[cells]);
57  const IntArray& ibFaceIndex = dynamic_cast<const IntArray&>(_geomFields.ibFaceIndex[faces]);
58 
59  const StorageSite& ibFaces = mesh.getIBFaces();
60 
61  const VectorT3Array* ibVelocity = (ibFaces.getCount() > 0) ?
62  &(dynamic_cast<const VectorT3Array&>(_flowFields.velocity[mesh.getIBFaces()])) : 0;
63 
64  // the net flux from ib faces
65  T boundaryFlux(0);
66 
67  const int nFaces = faces.getCount();
68  for(int f=0; f<nFaces; f++)
69  {
70  const int c0 = faceCells(f,0);
71  const int c1 = faceCells(f,1);
72  const VectorT3 ds=cellCentroid[c1]-cellCentroid[c0];
73  const VectorT3& Af = faceArea[f];
74 
75  const T diffMetric = faceAreaMag[f]*faceAreaMag[f]/dot(Af,ds);
76 
77  const T momApBar0 = (momAp[c0][0]+momAp[c0][1]+momAp[c0][2])/3.0;
78  const T momApBar1 = isSymmetry ? momApBar0 : (momAp[c1][0]+momAp[c1][1]+momAp[c1][2])/3.0 ;
79  const T momApBarFace = momApBar0 + momApBar1;
80 
81  const T VdotA0 = dot(V[c0],Af) - OneMinusmomURF*dot(Vprev[c0],Af);
82  const T VdotA1 = dot(V[c1],Af) - OneMinusmomURF*dot(Vprev[c1],Af);
83 
84 
85  const T dpf = cellVolume[c0]*(pGrad[c0]*ds) + cellVolume[c1]*(pGrad[c1]*ds);
86  // const T dpf = (cellVolume[c0]*(pGrad[c0]*ds) + cellVolume[c1]*(pGrad[c1]*ds))/
87  //(cellVolume[c0]+cellVolume[c1]) - p[c1] + p[c0];
88 
89  const T Vn = (VdotA0*momApBar0 + VdotA1*momApBar1 -dpf*diffMetric) / momApBarFace;
90  //const T Vn = (VdotA0*momApBar0 + VdotA1*momApBar1 -
91  // (cellVolume[c0]+cellVolume[c1])*dpf*diffMetric) / momApBarFace;
92 
93  const T rhoF = 0.5*(rho[c0]+rho[c1]);
94  const T aByMomAp = Af[0]*Af[0] / (momAp[c0][0] + momAp[c1][0]) +
95  Af[1]*Af[1] / (momAp[c0][1] + momAp[c1][1]) +
96  Af[2]*Af[2] / (momAp[c0][2] + momAp[c1][2]);
97 
98 
99  const T pCoeff = rhoF*aByMomAp*(cellVolume[c0]+cellVolume[c1])/(dot(Af,ds));
100 
101  if ((ibType[c0] == Mesh::IBTYPE_FLUID) &&
102  (ibType[c1] == Mesh::IBTYPE_FLUID))
103  {
104  massFlux[f] = rhoF*Vn - pCoeff*(p[c0]-p[c1]) + (1-momURF)*massFlux[f];
105 
106  if (isSymmetry) massFlux[f] = 0.;
107 
108  //massFlux[f] = rhoF*Vn + OneMinusmomURF*massFlux[f];
109 
110  rCell[c0] -= massFlux[f];
111  rCell[c1] += massFlux[f];
112 
113  ppAssembler.getCoeff01(f) -=pCoeff;
114  ppAssembler.getCoeff10(f) -=pCoeff;
115 
116  ppDiag[c0] += pCoeff;
117  ppDiag[c1] += pCoeff;
118  if (isSymmetry)
119  {
120  ppDiag[c0] -= ppAssembler.getCoeff01(f);
121  ppAssembler.getCoeff01(f) =0;
122  rCell[c1] = 0;
123  ppMatrix.setBoundary(c1);
124  }
125  }
126  else if (((ibType[c0] == Mesh::IBTYPE_FLUID)
127  && (ibType[c1] == Mesh::IBTYPE_BOUNDARY)) ||
128  ((ibType[c1] == Mesh::IBTYPE_FLUID)
129  && (ibType[c0] == Mesh::IBTYPE_BOUNDARY)))
130  {
131  const int ibFace = ibFaceIndex[f];
132  if (ibFace < 0)
133  throw CException("invalid ib face index");
134 
135  const VectorT3& faceVelocity = (*ibVelocity)[ibFace];
136 
137  // this is an iBFace, determine which cell is interior and
138  // which boundary. Treat as a fixed flux boundary.
139  if (ibType[c0] == Mesh::IBTYPE_FLUID)
140  {
141  massFlux[f]= rho[c0]*dot(Af,faceVelocity);
142  rCell[c0] -= massFlux[f];
143  rCell[c1] = 0;
144  ppMatrix.setDirichlet(c1);
145  boundaryFlux += massFlux[f];
146  }
147  else
148  {
149  rCell[c0] = 0;
150 
151  ppMatrix.setDirichlet(c0);
152 
153  // skip c1 if this is a ghost cell since the other mesh will
154  // compute the right face flux
155  if (c1 < nCellsInterior)
156  {
157  massFlux[f]= rho[c1]*dot(Af,faceVelocity);
158  rCell[c1] += massFlux[f];
159  boundaryFlux -= massFlux[f];
160  }
161  else
162  {
163  rCell[c1] = 0;
164  ppAssembler.getCoeff10(f) =0;
165  ppDiag[c1] = -1;
166  }
167  }
168 
169  }
170  else
171  {
172  if ((ibType[c0] == Mesh::IBTYPE_FLUID) ||
173  (ibType[c1] == Mesh::IBTYPE_FLUID))
174  throw CException("invalid face to skip");
175 
176  // setup to get zero corrections
177  massFlux[f]=0;
178  ppDiag[c0] = -1;
179  ppDiag[c1] = -1;
180  ppMatrix.setDirichlet(c0);
181  ppMatrix.setDirichlet(c1);
182  }
183  }
184 
185 #ifdef PV_COUPLED
186  if (mfmatrix.hasMatrix(pIndex,vIndex))
187  {
188  PVMatrix& pvMatrix =
189  dynamic_cast<PVMatrix&>(mfmatrix.getMatrix(pIndex,vIndex));
190 
191  PVAssembler& pvAssembler = pvMatrix.getPairWiseAssembler(faceCells);
192  PVDiagArray& pvDiag = pvMatrix.getDiag();
193 
194  for(int f=0; f<nFaces; f++)
195  {
196  const int c0 = faceCells(f,0);
197  const int c1 = faceCells(f,1);
198  const VectorT3& Af = faceArea[f];
199 
200  const T momApBar0 = (momAp[c0][0]+momAp[c0][1]+momAp[c0][2])/3.0;
201  const T momApBar1 = (momAp[c1][0]+momAp[c1][1]+momAp[c1][2])/3.0;
202  const T momApBarFace = momApBar0 + momApBar1;
203  const T rhoF = 0.5*(rho[c0]+rho[c1]);
204 
205  VectorT3T coeff0(rhoF*momApBar0/momApBarFace*Af);
206  VectorT3T coeff1(rhoF*momApBar1/momApBarFace*Af);
207 
208 
209  pvAssembler.getCoeff01(f) -=coeff1;
210  pvAssembler.getCoeff10(f) +=coeff0;
211 
212  pvDiag[c0] -= coeff0;
213  pvDiag[c1] += coeff1;
214  }
215  }
216 #endif
217  return boundaryFlux;
218 }
219 
220 
221 void correctVelocityInterior(const Mesh& mesh,
222  const StorageSite& faces,
223  const MultiField& ppField,
224  const bool isSymmetry = false)
225 {
226  const StorageSite& cells = mesh.getCells();
227  const int nCellsInterior = cells.getSelfCount();
228 
229  const VectorT3Array& faceArea = dynamic_cast<const VectorT3Array&>(_geomFields.area[faces]);
230  const VectorT3Array& cellCentroid = dynamic_cast<const VectorT3Array&>(_geomFields.coordinate[cells]);
231  const CRConnectivity& faceCells = mesh.getFaceCells(faces);
232 
233  MultiField::ArrayIndex pIndex(&_flowFields.pressure,&cells);
234  MultiField::ArrayIndex vIndex(&_flowFields.velocity,&cells);
235  const VVDiagArray& momAp = dynamic_cast<const VVDiagArray&>((*_momApField)[cells]);
236 
237  VectorT3Array& V = dynamic_cast<VectorT3Array&>(_flowFields.velocity[cells]);
238  const TArray& pp = dynamic_cast<const TArray&>(ppField[pIndex]);
239  const TArray& rho = dynamic_cast<const TArray&>(_flowFields.density[cells]);
240  const TArray& cellVolume = dynamic_cast<const TArray&>(_geomFields.volume[cells]);
241 
242  const IntArray& ibType = dynamic_cast<const IntArray&>(_geomFields.ibType[cells]);
243  const int nFaces = faces.getCount();
244  for(int f=0; f<nFaces; f++)
245  {
246  const int c0 = faceCells(f,0);
247  const int c1 = faceCells(f,1);
248 
249  if ((ibType[c0] == Mesh::IBTYPE_FLUID) &&
250  (ibType[c1] == Mesh::IBTYPE_FLUID))
251  {
252  const VectorT3 ds=cellCentroid[c1]-cellCentroid[c0];
253  const VectorT3& Af = faceArea[f];
254 
255  const T aByMomAp0 = Af[0]*Af[0] / momAp[c0][0] +
256  Af[1]*Af[1] / momAp[c0][1] +
257  Af[2]*Af[2] / momAp[c0][2];
258 
259  const T aByMomAp1 = Af[0]*Af[0] / momAp[c1][0] +
260  Af[1]*Af[1] / momAp[c1][1] +
261  Af[2]*Af[2] / momAp[c1][2];
262 
263  const T Adotes = dot(Af,ds)/mag(ds);
264  const T coeff0 = cellVolume[c0]*rho[c0]*aByMomAp0/Adotes;
265  const T coeff1 = isSymmetry ? coeff0 :
266  cellVolume[c1]*rho[c1]*aByMomAp1/Adotes;
267 
268  const T ppFace = (coeff0*pp[c0]+coeff1*pp[c1])/(coeff0+coeff1);
269  const VectorT3 ppA = ppFace*faceArea[f];
270 
271  V[c0] += ppA/momAp[c0];
272  if (!isSymmetry)
273  V[c1] -= ppA/momAp[c1];
274  }
275  else if (((ibType[c0] == Mesh::IBTYPE_FLUID)
276  && (ibType[c1] == Mesh::IBTYPE_BOUNDARY)) ||
277  ((ibType[c1] == Mesh::IBTYPE_FLUID)
278  && (ibType[c0] == Mesh::IBTYPE_BOUNDARY)))
279  {
280  // this is an iBFace, determine which cell is interior and
281  // which boundary. Correct the interior cell's velocity
282  // using the cell pressure correction as the face pressure
283  // correction
284  if (ibType[c0] == Mesh::IBTYPE_FLUID)
285  {
286  const T ppFace = pp[c0];
287  const VectorT3 ppA = ppFace*faceArea[f];
288 
289  V[c0] += ppA/momAp[c0];
290  }
291  else if (c1 < nCellsInterior)
292  {
293  const T ppFace = pp[c1];
294  const VectorT3 ppA = ppFace*faceArea[f];
295 
296  V[c1] -= ppA/momAp[c1];
297  }
298  }
299  // nothing needs to be done for the solid/solid or solid/ib faces
300  }
301 }
302 
304  const StorageSite& faces,
305  const bool isSymmetry=false)
306 {
307  const StorageSite& cells = mesh.getCells();
308 
309  const VectorT3Array& faceArea = dynamic_cast<const VectorT3Array&>(_geomFields.area[faces]);
310  const VectorT3Array& cellCentroid = dynamic_cast<const VectorT3Array&>(_geomFields.coordinate[cells]);
311  const CRConnectivity& faceCells = mesh.getFaceCells(faces);
312 
313  MultiField::ArrayIndex vIndex(&_flowFields.velocity,&cells);
314  const VVDiagArray& momAp = dynamic_cast<const VVDiagArray&>((*_momApField)[cells]);
315 
316  const TArray& pCell = dynamic_cast<const TArray&>(_flowFields.pressure[cells]);
317  TArray& pFace = dynamic_cast<TArray&>(_flowFields.pressure[faces]);
318  const TArray& rho = dynamic_cast<const TArray&>(_flowFields.density[cells]);
319  const TArray& cellVolume = dynamic_cast<const TArray&>(_geomFields.volume[cells]);
320 
321  const int nFaces = faces.getCount();
322  const IntArray& ibType = dynamic_cast<const IntArray&>(_geomFields.ibType[cells]);
323  for(int f=0; f<nFaces; f++)
324  {
325  const int c0 = faceCells(f,0);
326  const int c1 = faceCells(f,1);
327 
328  if ((ibType[c0] == Mesh::IBTYPE_FLUID) &&
329  (ibType[c1] == Mesh::IBTYPE_FLUID))
330  {
331  const VectorT3 ds=cellCentroid[c1]-cellCentroid[c0];
332  const VectorT3& Af = faceArea[f];
333 
334  const T aByMomAp0 = Af[0]*Af[0] / momAp[c0][0] +
335  Af[1]*Af[1] / momAp[c0][1] +
336  Af[2]*Af[2] / momAp[c0][2];
337 
338  const T aByMomAp1 = Af[0]*Af[0] / momAp[c1][0] +
339  Af[1]*Af[1] / momAp[c1][1] +
340  Af[2]*Af[2] / momAp[c1][2];
341 
342  const T Adotes = dot(Af,ds)/mag(ds);
343  const T coeff0 = cellVolume[c0]*rho[c0]*aByMomAp0/Adotes;
344  const T coeff1 = isSymmetry ? coeff0 :
345  cellVolume[c1]*rho[c1]*aByMomAp1/Adotes;
346 
347  pFace[f] = (coeff0*pCell[c0]+coeff1*pCell[c1])/(coeff0+coeff1);
348  }
349  else if (((ibType[c0] == Mesh::IBTYPE_FLUID)
350  && (ibType[c1] == Mesh::IBTYPE_BOUNDARY)) ||
351  ((ibType[c1] == Mesh::IBTYPE_FLUID)
352  && (ibType[c0] == Mesh::IBTYPE_BOUNDARY)))
353  {
354  // this is an iBFace, determine which cell is interior and
355  // which boundary. copy pressure from the fluid cell
356  if (ibType[c0] == Mesh::IBTYPE_FLUID)
357  {
358  pFace[f] = pCell[c0];
359  }
360  else
361  {
362  pFace[f] = pCell[c1];
363  }
364  }
365  else
366  // for solid/solid and solid/ib faces pressure is never used
367  pFace[f]=0;
368  }
369 }
370 
371 void correctMassFluxInterior(const Mesh& mesh,
372  const StorageSite& faces,
373  MultiFieldMatrix& mfmatrix,
374  const MultiField& xField)
375 {
376  const StorageSite& cells = mesh.getCells();
377  const CRConnectivity& faceCells = mesh.getFaceCells(faces);
378 
379  MultiField::ArrayIndex pIndex(&_flowFields.pressure,&cells);
380  const TArray& pp = dynamic_cast<const TArray&>(xField[pIndex]);
381 
382  PPMatrix& ppMatrix =
383  dynamic_cast<PPMatrix&>(mfmatrix.getMatrix(pIndex,pIndex));
384 
385  PPAssembler& ppAssembler = ppMatrix.getPairWiseAssembler(faceCells);
386 
387  TArray& massFlux = dynamic_cast<TArray&>(_flowFields.massFlux[faces]);
388 
389  const int nFaces = faces.getCount();
390  for(int f=0; f<nFaces; f++)
391  {
392  const int c0 = faceCells(f,0);
393  const int c1 = faceCells(f,1);
394 
395  // should work for ib and ib/solid etc faces as well since the
396  // coefficients at such faces are all zero
397  massFlux[f] -= ppAssembler.getCoeff01(f)*pp[c1] -
398  ppAssembler.getCoeff10(f)*pp[c0];
399  }
400 
401 #ifdef PV_COUPLED
402  MultiField::ArrayIndex vIndex(&_flowFields.velocity,&cells);
403  if (mfmatrix.hasMatrix(pIndex,vIndex))
404  {
405  PVMatrix& pvMatrix =
406  dynamic_cast<PVMatrix&>(mfmatrix.getMatrix(pIndex,vIndex));
407 
408  PVAssembler& pvAssembler = pvMatrix.getPairWiseAssembler(faceCells);
409  const VectorT3Array& Vp = dynamic_cast<const VectorT3Array&>(xField[vIndex]);
410 
411  for(int f=0; f<nFaces; f++)
412  {
413  const int c0 = faceCells(f,0);
414  const int c1 = faceCells(f,1);
415 
416  massFlux[f] += pvAssembler.getCoeff01(f)*Vp[c1] +
417  pvAssembler.getCoeff10(f)*Vp[c0];
418  }
419  }
420 #endif
421 }
422 
423 #endif
Matrix & getMatrix(const Index &rowIndex, const Index &colIndex)
int getSelfCount() const
Definition: StorageSite.h:40
const StorageSite & getIBFaces() const
Definition: Mesh.h:111
bool hasMatrix(const Index &rowIndex, const Index &colIndex) const
Definition: Mesh.h:49
T mag(const Vector< T, 3 > &a)
Definition: Vector.h:260
void updateFacePressureInterior(const Mesh &mesh, const StorageSite &faces, const bool isSymmetry=false)
void correctVelocityInterior(const Mesh &mesh, const StorageSite &faces, const MultiField &ppField, const bool isSymmetry=false)
T discretizeMassFluxInterior(const Mesh &mesh, const StorageSite &faces, MultiFieldMatrix &mfmatrix, const MultiField &xField, MultiField &rField, const bool isSymmetry=false)
pair< const Field *, const StorageSite * > ArrayIndex
Definition: MultiField.h:21
const StorageSite & getCells() const
Definition: Mesh.h:109
void correctMassFluxInterior(const Mesh &mesh, const StorageSite &faces, MultiFieldMatrix &mfmatrix, const MultiField &xField)
const CRConnectivity & getFaceCells(const StorageSite &site) const
Definition: Mesh.cpp:388
int getCount() const
Definition: StorageSite.h:39
T dot(const Vector< T, 3 > &a, const Vector< T, 3 > &b)
Definition: Vector.h:253