Memosa-FVM  0.2
StructureSourceDiscretization.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 _STRUCTURESOURCEDISCRETIZATION_H_
6 #define _STRUCTURESOURCEDISCRETIZATION_H_
7 
8 #include "Field.h"
9 #include "MultiField.h"
10 #include "MultiFieldMatrix.h"
11 #include "Mesh.h"
12 #include "Discretization.h"
13 #include "StorageSite.h"
14 #include "GeomFields.h"
15 #include "CRConnectivity.h"
16 #include "CRMatrixRect.h"
17 #include "Vector.h"
18 #include "GradientModel.h"
19 
20 template<class T, class Diag, class OffDiag>
22 {
23 public:
24 
25  typedef Array<T> TArray;
30 
32  typedef typename CCMatrix::DiagArray DiagArray;
34 
37 
39  const GeomFields& geomFields,
40  Field& varField,
41  const Field& muField,
42  const Field& lambdaField,
43  const Field& alphaField,
44  const Field& varGradientField,
45  const Field& temperatureField,
46  const T& referenceTemperature,
47  const T& residualXXStress,
48  const T& residualYYStress,
49  const T& residualZZStress,
50  const bool& thermo,
51  const bool& residualStress,
52  bool fullLinearization=true) :
53  Discretization(meshes),
54  _geomFields(geomFields),
55  _varField(varField),
56  _muField(muField),
57  _lambdaField(lambdaField),
58  _alphaField(alphaField),
59  _varGradientField(varGradientField),
60  _temperatureField(temperatureField),
61  _referenceTemperature(referenceTemperature),
62  _residualXXStress(residualXXStress),
63  _residualYYStress(residualYYStress),
64  _residualZZStress(residualZZStress),
65  _thermo(thermo),
66  _residualStress(residualStress),
67  _fullLinearization(fullLinearization)
68  {}
69 
70  void discretize(const Mesh& mesh, MultiFieldMatrix& mfmatrix,
71  MultiField& xField, MultiField& rField)
72  {
73  const StorageSite& iFaces = mesh.getInteriorFaceGroup().site;
74 
75  discretizeFaces(mesh, iFaces, mfmatrix, xField, rField, false, false);
76 
77  /*
78  foreach(const FaceGroupPtr fgPtr, mesh.getInterfaceGroups())
79  {
80  const FaceGroup& fg = *fgPtr;
81  const StorageSite& faces = fg.site;
82  discretizeFaces(mesh, faces, mfmatrix, xField, rField, false, false);
83  }
84  */
85 
86  // boundaries and interfaces
87  foreach(const FaceGroupPtr fgPtr, mesh.getAllFaceGroups())
88  {
89  const FaceGroup& fg = *fgPtr;
90  const StorageSite& faces = fg.site;
91  if (fg.groupType!="interior")
92  {
93  discretizeFaces(mesh, faces, mfmatrix, xField, rField,
94  fg.groupType!="interface",
95  fg.groupType=="symmetry");
96  }
97  }
98  }
99 
100 
101  void discretizeFaces(const Mesh& mesh, const StorageSite& faces,
102  MultiFieldMatrix& mfmatrix,
103  MultiField& xField, MultiField& rField,
104  const bool isBoundary, const bool isSymmetry)
105  {
106  const StorageSite& cells = mesh.getCells();
107 
108  const MultiField::ArrayIndex cVarIndex(&_varField,&cells);
109 
110  const VectorT3Array& faceArea =
111  dynamic_cast<const VectorT3Array&>(_geomFields.area[faces]);
112 
113  const TArray& faceAreaMag =
114  dynamic_cast<const TArray&>(_geomFields.areaMag[faces]);
115 
116  const VectorT3Array& cellCentroid =
117  dynamic_cast<const VectorT3Array&>(_geomFields.coordinate[cells]);
118 
119  const VectorT3Array& faceCentroid =
120  dynamic_cast<const VectorT3Array&>(_geomFields.coordinate[faces]);
121 
122 
123  const TArray& cellVolume =
124  dynamic_cast<const TArray&>(_geomFields.volume[cells]);
125 
126  const CRConnectivity& faceCells = mesh.getFaceCells(faces);
127 
128  VectorT3Array& rCell = dynamic_cast<VectorT3Array&>(rField[cVarIndex]);
129  const VectorT3Array& xCell = dynamic_cast<const VectorT3Array&>(xField[cVarIndex]);
130 
131  const VGradArray& vGradCell =
132  dynamic_cast<const VGradArray&>(_varGradientField[cells]);
133 
134  const TArray& muCell =
135  dynamic_cast<const TArray&>(_muField[cells]);
136 
137  const TArray& lambdaCell =
138  dynamic_cast<const TArray&>(_lambdaField[cells]);
139 
140  const TArray& alphaCell =
141  dynamic_cast<const TArray&>(_alphaField[cells]);
142 
143  const TArray& temperatureCell =
144  dynamic_cast<const TArray&>(_temperatureField[cells]);
145 
146  CCMatrix& matrix = dynamic_cast<CCMatrix&>(mfmatrix.getMatrix(cVarIndex,
147  cVarIndex));
148  CCAssembler& assembler = matrix.getPairWiseAssembler(faceCells);
149  DiagArray& diag = matrix.getDiag();
150 
151 
152  const int nFaces = faces.getCount();
153 
155  const CRConnectivity& cellCells = vgMatrix.getConnectivity();
156  const Array<int>& ccRow = cellCells.getRow();
157  const Array<int>& ccCol = cellCells.getCol();
158 
159  const int nInteriorCells = cells.getSelfCount();
160 
161  const T two(2.0);
162  const T three(3.0);
163 
164  for(int f=0; f<nFaces; f++)
165  {
166  const int c0 = faceCells(f,0);
167  const int c1 = faceCells(f,1);
168 
169  const VectorT3& Af = faceArea[f];
170  const VectorT3 en = Af/faceAreaMag[f];
171 
172  VectorT3 ds=cellCentroid[c1]-cellCentroid[c0];
173 
174  T vol0 = cellVolume[c0];
175  T vol1 = cellVolume[c1];
176 
177  T wt0 = vol0/(vol0+vol1);
178  T wt1 = vol1/(vol0+vol1);
179 
180  if (isBoundary && !isSymmetry)
181  {
182  wt0 = T(1.0);
183  wt1 = T(0.);
184  }
185 
186  T faceMu(1.0);
187  T faceLambda(1.0);
188  T faceAlpha(1.0);
189  T faceTemperature(1.0);
190 
191  Diag& a00 = diag[c0];
192  Diag& a11 = diag[c1];
193  OffDiag& a01 = assembler.getCoeff01(f);
194  OffDiag& a10 = assembler.getCoeff10(f);
195 
196  if (vol0 == 0.)
197  {
198  faceMu = muCell[c1];
199  faceLambda = lambdaCell[c1];
200  faceAlpha = alphaCell[c1];
201  faceTemperature = temperatureCell[c1];
202  }
203  else if (vol1 == 0.)
204  {
205  faceMu = muCell[c0];
206  faceLambda = lambdaCell[c0];
207  faceAlpha = alphaCell[c0];
208  faceTemperature = temperatureCell[c0];
209  }
210  else
211  {
212  faceMu = harmonicAverage(muCell[c0],muCell[c1]);
213  faceLambda = harmonicAverage(lambdaCell[c0],lambdaCell[c1]);
214  faceAlpha = harmonicAverage(alphaCell[c0],alphaCell[c1]);
215  faceTemperature = harmonicAverage(temperatureCell[c0],temperatureCell[c1]);
216  }
217 
218  faceMu = muCell[c0]*wt0 + muCell[c1]*wt1;
219  faceLambda = lambdaCell[c0]*wt0 + lambdaCell[c1]*wt1;
220  faceAlpha = alphaCell[c0]*wt0 + alphaCell[c1]*wt1;
221  faceTemperature = temperatureCell[c0]*wt0 + temperatureCell[c1]*wt1;
222 
223  const VGradType gradF = (vGradCell[c0]*wt0 + vGradCell[c1]*wt1);
224 
227  VectorT3 residualSource(NumTypeTraits<VectorT3>::getZero());
228  const T divU = (gradF[0][0] + gradF[1][1] + gradF[2][2]);
229 
230  const T diffMetric = faceAreaMag[f]*faceAreaMag[f]/dot(faceArea[f],ds);
231  const VectorT3 secondaryCoeff = faceMu*(faceArea[f]-ds*diffMetric);
232 
233  // mu*grad U ^ T + lambda * div U I
234  source[0] = faceMu*(gradF[0][0]*Af[0] + gradF[0][1]*Af[1] + gradF[0][2]*Af[2])
235  + faceLambda*divU*Af[0];
236 
237  source[1] = faceMu*(gradF[1][0]*Af[0] + gradF[1][1]*Af[1] + gradF[1][2]*Af[2])
238  + faceLambda*divU*Af[1];
239 
240  source[2] = faceMu*(gradF[2][0]*Af[0] + gradF[2][1]*Af[1] + gradF[2][2]*Af[2])
241  + faceLambda*divU*Af[2];
242 
243  if(_thermo)
244  {
245  if(mesh.getDimension()==2)
246  thermalSource -= (two*faceLambda+two*faceMu)*faceAlpha*(faceTemperature-_referenceTemperature)*Af;
247  else
248  thermalSource -= (three*faceLambda+two*faceMu)*faceAlpha*(faceTemperature-_referenceTemperature)*Af;
249  }
250 
251  if(_residualStress)
252  {
253  residualSource[0] = _residualXXStress*Af[0];
254  residualSource[1] = _residualYYStress*Af[1];
255  residualSource[2] = _residualZZStress*Af[2];
256  }
257 
260  if (_fullLinearization)
261  {
262  // loop over level 0 neighbors
263  for(int nnb = ccRow[c0]; nnb<ccRow[c0+1]; nnb++)
264  {
265  const int nb = ccCol[nnb];
266 
267  // get the coefficient from the gradient matrix that uses modified cellCells
268  // getting a copy rather than reference since we might modify it
269  VectorT3 g_nb = vgMatrix.getCoeff(c0,nb);
270 #if 1
271  if (isSymmetry)
272  {
273  const T gnb_dot_nx2 = T(2.0)*dot(en,g_nb);
274  g_nb = gnb_dot_nx2*en;
275  }
276 #endif
277  Diag coeff;
278 
279  for(int i=0; i<3; i++)
280  {
281  for(int j=0; j<3; j++)
282  {
283  coeff(i,j) = wt0*(faceMu*Af[j]*g_nb[i]
284  + faceLambda*Af[i]*g_nb[j]
285  );
286  }
287 
288  for(int k=0; k<3; k++)
289  coeff(i,i) += wt0*secondaryCoeff[k]*g_nb[k];
290  }
291 #if 0
292  if (isSymmetry)
293  {
295 
296  for(int i=0;i<3;i++)
297  for(int j=0; j<3; j++)
298  {
299  if (i==j)
300  R(i,j) = 1.0 - 2*en[i]*en[j];
301  else
302  R(i,j) = - 2*en[i]*en[j];
303  }
304 
305  Diag coeff1(R*coeff*R);
306  coeff += coeff1;
307 
308  }
309 #endif
310  OffDiag& a0_nb = matrix.getCoeff(c0,nb);
311 
312  a0_nb += coeff;
313  a00 -= coeff;
314  a10 += coeff;
315 
316  if (c1 != nb)
317  {
318  // if the coefficient does not exist we assume c1
319  // is a ghost cell for which we don't want an
320  // equation in this matrix
321  if (matrix.hasCoeff(c1,nb))
322  {
323  OffDiag& a1_nb = matrix.getCoeff(c1,nb);
324  a1_nb -= coeff;
325  }
326  }
327  else
328  a11 -= coeff;
329  }
330 
331 
332  if (!isBoundary)
333  {
334  for(int nnb = ccRow[c1]; nnb<ccRow[c1+1]; nnb++)
335  {
336  const int nb = ccCol[nnb];
337  const VectorT3& g_nb = vgMatrix.getCoeff(c1,nb);
338 
339  Diag coeff;
340 
341  for(int i=0; i<3; i++)
342  {
343  for(int j=0; j<3; j++)
344  {
345  coeff(i,j) = wt1*(faceMu*Af[j]*g_nb[i]
346  + faceLambda*Af[i]*g_nb[j]
347  );
348  }
349 
350  for(int k=0; k<3; k++)
351  coeff(i,i) += wt1*secondaryCoeff[k]*g_nb[k];
352  }
353 
354 
355  if (matrix.hasCoeff(c1,nb))
356  {
357  OffDiag& a1_nb = matrix.getCoeff(c1,nb);
358  a1_nb -= coeff;
359  a11 += coeff;
360  }
361  a01 -= coeff;
362 
363 
364  if (c0 != nb)
365  {
366  OffDiag& a0_nb = matrix.getCoeff(c0,nb);
367 
368  a0_nb += coeff;
369  }
370  else
371  a00 += coeff;
372 
373  }
374  }
375  }
376 
377  // mu*gradU, primary part
378 
379 
380  source += faceMu*diffMetric*(xCell[c1]-xCell[c0]);
381 
382  // mu*gradU, secondart part
383 
384 
385  source += gradF*secondaryCoeff;
386 
387  // add flux to the residual of c0 and c1
388  rCell[c0] += source;
389  rCell[c1] -= source;
390 
391  // add flux due to thermal Stress to the residual of c0 and c1
392  rCell[c0] += thermalSource;
393  rCell[c1] -= thermalSource;
394 
395  // add flux due to residual Stress to the residual of c0 and c1
396  rCell[c0] += residualSource;
397  rCell[c1] -= residualSource;
398 
399 
400  // for Jacobian, use 2*mu + lambda as the diffusivity
401  const T faceDiffusivity = faceMu;
402  const T diffCoeff = faceDiffusivity*diffMetric;
403 
404 
405  a01 +=diffCoeff;
406  a10 +=diffCoeff;
407 
408 
409  a00 -= diffCoeff;
410  a11 -= diffCoeff;
411 
412  }
413  }
414 
415 
416 private:
419  const Field& _muField;
428  const bool _thermo;
429  const bool _residualStress;
430  const bool _fullLinearization;
431 };
432 
433 #endif
const Array< int > & getCol() const
const Array< int > & getRow() const
const FaceGroup & getInteriorFaceGroup() const
Definition: Mesh.h:181
Matrix & getMatrix(const Index &rowIndex, const Index &colIndex)
shared_ptr< FaceGroup > FaceGroupPtr
Definition: Mesh.h:46
int getSelfCount() const
Definition: StorageSite.h:40
Field coordinate
Definition: GeomFields.h:19
T harmonicAverage(const T &x0, const T &x1)
Definition: Mesh.h:28
StructureSourceDiscretization(const MeshList &meshes, const GeomFields &geomFields, Field &varField, const Field &muField, const Field &lambdaField, const Field &alphaField, const Field &varGradientField, const Field &temperatureField, const T &referenceTemperature, const T &residualXXStress, const T &residualYYStress, const T &residualZZStress, const bool &thermo, const bool &residualStress, bool fullLinearization=true)
const FaceGroupList & getAllFaceGroups() const
Definition: Mesh.h:193
Definition: Field.h:14
OffDiag & getCoeff(const int i, const int j)
Definition: CRMatrix.h:836
bool hasCoeff(const int i, const int j)
Definition: CRMatrix.h:846
Definition: Mesh.h:49
OffDiag & getCoeff10(const int np)
Definition: CRMatrix.h:131
Coord & getCoeff(const int i, const int j)
Array< Diag > & getDiag()
Definition: CRMatrix.h:856
CCMatrix::PairWiseAssembler CCAssembler
void discretizeFaces(const Mesh &mesh, const StorageSite &faces, MultiFieldMatrix &mfmatrix, MultiField &xField, MultiField &rField, const bool isBoundary, const bool isSymmetry)
string groupType
Definition: Mesh.h:42
const CRConnectivity & getConnectivity() const
pair< const Field *, const StorageSite * > ArrayIndex
Definition: MultiField.h:21
void discretize(const Mesh &mesh, MultiFieldMatrix &mfmatrix, MultiField &xField, MultiField &rField)
VGradModelType::GradMatrixType VGradMatrix
const StorageSite & getCells() const
Definition: Mesh.h:109
Field volume
Definition: GeomFields.h:26
OffDiag & getCoeff01(const int np)
Definition: CRMatrix.h:126
Array< Gradient< VectorT3 > > VGradArray
const CRConnectivity & getFaceCells(const StorageSite &site) const
Definition: Mesh.cpp:388
static GradMatrixType & getGradientMatrix(const Mesh &mesh, const GeomFields &geomFields)
Definition: Array.h:14
int getCount() const
Definition: StorageSite.h:39
Field area
Definition: GeomFields.h:23
CRMatrix< Diag, OffDiag, VectorT3 > CCMatrix
PairWiseAssembler & getPairWiseAssembler(const CRConnectivity &pairs)
Definition: CRMatrix.h:867
int getDimension() const
Definition: Mesh.h:105
Field areaMag
Definition: GeomFields.h:25
T dot(const Vector< T, 3 > &a, const Vector< T, 3 > &b)
Definition: Vector.h:253
vector< Mesh * > MeshList
Definition: Mesh.h:439
StorageSite site
Definition: Mesh.h:40