63 typedef typename PVMatrix::DiagArray PVDiagArray;
64 typedef typename PVMatrix::PairWiseAssembler PVAssembler;
67 typedef typename VPMatrix::DiagArray VPDiagArray;
68 typedef typename VPMatrix::PairWiseAssembler VPAssembler;
87 _geomFields(geomFields),
88 _flowFields(thermalFields),
89 _velocityGradientModel(
_meshes,_flowFields.velocity,
90 _flowFields.velocityGradient,_geomFields),
91 _pressureGradientModel(
_meshes,_flowFields.pressure,
92 _flowFields.pressureGradient,_geomFields),
93 _initialMomentumNorm(),
94 _initialContinuityNorm(),
97 const int numMeshes =
_meshes.size();
98 for (
int n=0; n<numMeshes; n++)
104 _vcMap[mesh.
getID()] = vc;
108 if (_bcMap.find(fg.
id) == _bcMap.end())
115 bc->
bcType =
"NoSlipWall";
117 else if ((fg.
groupType ==
"velocity-inlet"))
119 bc->
bcType =
"VelocityBoundary";
121 else if ((fg.
groupType ==
"pressure-inlet") ||
124 bc->
bcType =
"PressureBoundary";
131 throw CException(
"FlowModel: unknown face group type "
150 const int numMeshes =
_meshes.size();
151 for (
int n=0; n<numMeshes; n++)
163 initialVelocity[0] = _options[
"initialXVelocity"];
164 initialVelocity[1] = _options[
"initialYVelocity"];
165 initialVelocity[2] = _options[
"initialZVelocity"];
166 *vCell = initialVelocity;
168 _flowFields.velocity.addArray(cells,vCell);
171 uparallelCell ->zero();
172 _flowFields.uparallel.addArray(cells,uparallelCell);
176 _flowFields.tau.addArray(faces,tauCell);
179 TauWallCell ->zero();
180 _flowFields.tauwall.addArray(faces,TauWallCell);
188 if (_options.transient)
190 _flowFields.velocityN1.addArray(cells,
191 dynamic_pointer_cast<ArrayBase>(vCell->newCopy()));
192 if (_options.timeDiscretizationOrder > 1)
193 _flowFields.velocityN2.addArray(cells,
194 dynamic_pointer_cast<ArrayBase>(vCell->newCopy()));
200 *pCell = _options[
"initialPressure"];
201 *pFace = _options[
"initialPressure"];
202 _flowFields.pressure.addArray(cells,pCell);
203 _flowFields.pressure.addArray(faces,pFace);
207 *rhoCell = vc[
"density"];
208 _flowFields.density.addArray(cells,rhoCell);
211 *muCell = vc[
"viscosity"];
212 _flowFields.viscosity.addArray(cells,muCell);
214 shared_ptr<PGradArray> gradp(
new PGradArray(cells.
getCountLevel1()));
216 _flowFields.pressureGradient.addArray(cells,gradp);
220 _flowFields.continuityResidual.addArray(cells,ci);
227 const TArray& density = *rhoCell;
231 const int nFaces = faces.
getCount();
236 for(
int f=0; f<nFaces; f++)
238 const int c0 = faceCells(f,0);
239 const int c1 = faceCells(f,1);
241 mf[f] = 0.5*(density[c0]*
dot(V[c0],faceArea[f]) +
242 density[c1]*
dot(V[c1],faceArea[f]));
244 _flowFields.massFlux.addArray(faces,mfPtr);
253 _flowFields.momentumFlux.addArray(faces,momFlux);
256 cout <<
"interface init" <<endl;
260 InterfaceVelFace ->zero();
261 _flowFields.InterfaceVelocity.addArray(Intfaces,InterfaceVelFace);
263 shared_ptr<StressTensorArray> InterfaceStressFace(
new StressTensorArray(Intfaces.
getCount()));
264 InterfaceStressFace ->zero();
265 _flowFields.InterfaceStress.addArray(Intfaces,InterfaceStressFace);
267 shared_ptr<TArray> InterfacePressFace(
new TArray(Intfaces.
getCount()));
268 *InterfacePressFace = _options[
"initialPressure"];
269 _flowFields.InterfacePressure.addArray(Intfaces,InterfacePressFace);
271 shared_ptr<TArray> InterfaceDensityFace(
new TArray(Intfaces.
getCount()));
272 *InterfaceDensityFace =vc[
"density"];
273 _flowFields.InterfaceDensity.addArray(Intfaces,InterfaceDensityFace);
289 bVelocity(bc.
getVal(
"specifiedXVelocity"),
290 bc.
getVal(
"specifiedYVelocity"),
291 bc.
getVal(
"specifiedZVelocity"),
294 const int nFaces = faces.
getCount();
297 if ((bc.
bcType ==
"NoSlipWall") ||
298 (bc.
bcType ==
"SlipJump") ||
299 (bc.
bcType ==
"VelocityBoundary"))
302 TArray& massFlux =
dynamic_cast<TArray&
>(_flowFields.massFlux[faces]);
307 for(
int f=0; f<nFaces; f++)
309 const int c0 = faceCells(f,0);
310 massFlux[f] = density[c0]*
dot(bVelocity[f],faceArea[f]);
313 else if (bc.
bcType ==
"SpecifiedPressure")
315 T bp = bc[
"specifiedPressure"];
316 TArray& facePressure =
dynamic_cast<TArray&
>(_flowFields.pressure[faces]);
317 TArray& cellPressure =
dynamic_cast<TArray&
>(_flowFields.pressure[cells]);
318 for(
int f=0; f<nFaces; f++)
320 const int c1 = faceCells(f,1);
321 facePressure[f] = cellPressure[c1] = bp;
324 else if ((bc.
bcType ==
"Symmetry"))
326 TArray& massFlux =
dynamic_cast<TArray&
>(_flowFields.massFlux[faces]);
331 _flowFields.momentumFlux.addArray(faces,momFlux);
338 computeContinuityResidual();
340 _initialMomentumNorm =
MFRPtr();
341 _initialContinuityNorm =
MFRPtr();
350 const int numMeshes =
_meshes.size();
351 for (
int n=0; n<numMeshes; n++)
361 if (_options.timeDiscretizationOrder > 1)
372 if (_options.turbulent)
373 return _flowFields.totalviscosity;
375 return _flowFields.viscosity;
384 dynamic_cast<const VectorT3Array&
>(_flowFields.velocity[particles]);
386 const int numMeshes =
_meshes.size();
387 for (
int n=0; n<numMeshes; n++)
397 dynamic_cast<const IMatrix&
>
398 (*_geomFields._interpolationMatrices[key1]);
405 dynamic_cast<const IMatrix&
>
406 (*_geomFields._interpolationMatrices[key2]);
414 dynamic_cast<const VectorT3Array&
>(_flowFields.velocity[cells]);
419 mICV.multiplyAndAdd(*ibV,cV);
420 mIPV.multiplyAndAdd(*ibV,pV);
424 stringstream ss(stringstream::in | stringstream::out);
425 ss << MPI::COMM_WORLD.Get_rank();
426 string fname1 =
"IBVelocity_proc" + ss.str() +
".dat";
427 debugFile.open(fname1.c_str());
433 dynamic_cast<const VectorT3Array&
> (_geomFields.coordinate[faces]);
434 const double angV = 1.0;
440 for(
int f=0; f<ibFaces.
getCount();f++){
441 int fID = ibFaceList[f];
442 debugFile <<
"f=" << f << setw(10) <<
" fID = " << fID <<
" faceCentroid = " << faceCentroid[fID] <<
" ibV = " << (*ibV)[f] << endl;
449 _flowFields.velocity.addArray(ibFaces,ibV);
456 map<string,shared_ptr<ArrayBase> >&
462 (*niterArray)[0] = _niters;
465 if (_initialMomentumNorm)
468 _initialMomentumNorm->getArrayPtr(_flowFields.velocity);
478 if (_initialContinuityNorm)
481 _initialContinuityNorm->getArrayPtr(_flowFields.pressure);
499 _niters = niterArray[0];
506 _initialMomentumNorm->addArray(_flowFields.velocity,r);
513 _initialContinuityNorm->addArray(_flowFields.pressure,r);
516 computeContinuityResidual();
524 const int numMeshes =
_meshes.size();
525 for (
int n=0; n<numMeshes; n++)
532 ls.
getX().
addArray(vIndex,_flowFields.velocity.getArrayPtr(cells));
546 ls.
getX().
addArray(fIndex,_flowFields.momentumFlux.getArrayPtr(faces));
563 ls.
getX().
addArray(fIndex,_flowFields.momentumFlux.getArrayPtr(faces));
578 _velocityGradientModel.compute();
581 shared_ptr<Discretization>
584 _flowFields.velocity,
586 _flowFields.velocityGradient));
588 shared_ptr<Discretization>
591 _flowFields.velocity,
592 _flowFields.massFlux,
593 _flowFields.continuityResidual,
594 _flowFields.velocityGradient));
596 shared_ptr<Discretization>
600 _pressureGradientModel));
602 discretizations.push_back(dd);
603 discretizations.push_back(cd);
604 discretizations.push_back(pd);
606 if (_options.transient)
608 shared_ptr<Discretization>
611 _flowFields.velocity,
612 _flowFields.velocityN1,
613 _flowFields.velocityN2,
615 _options[
"timeStep"]));
617 discretizations.push_back(td);
621 shared_ptr<Discretization>
623 (
_meshes,_geomFields,_flowFields.velocity));
625 discretizations.push_back(ibm);
631 const int numMeshes =
_meshes.size();
632 for (
int n=0; n<numMeshes; n++)
640 const int nFaces = faces.
getCount();
647 _flowFields.velocity,
648 _flowFields.momentumFlux,
653 const TArray& massFlux =
dynamic_cast<const TArray&
>(_flowFields.massFlux[faces]);
657 bVelocity(bc.
getVal(
"specifiedXVelocity"),
658 bc.
getVal(
"specifiedYVelocity"),
659 bc.
getVal(
"specifiedZVelocity"),
662 if (bc.
bcType ==
"NoSlipWall")
664 gbc.applyDirichletBC(bVelocity);
666 else if (bc.
bcType ==
"SlipJump")
670 bc[
"accomodationCoefficient"],
673 else if ((bc.
bcType ==
"VelocityBoundary") ||
674 (bc.
bcType ==
"PressureBoundary"))
676 for(
int f=0; f<nFaces; f++)
678 if (massFlux[f] > 0.)
680 gbc.applyExtrapolationBC(f);
684 gbc.applyDirichletBC(f,bVelocity[f]);
687 if (bc.
bcType ==
"PressureBoundary")
693 else if ((bc.
bcType ==
"Symmetry"))
695 gbc.applySymmetryBC();
708 _flowFields.velocity,
709 _flowFields.momentumFlux,
717 shared_ptr<Discretization>
720 _options[
"momentumURF"]));
722 discretizations2.push_back(ud);
734 initMomentumLinearization(ls);
736 linearizeMomentum(ls);
741 _previousVelocity = dynamic_pointer_cast<
Field>(_flowFields.velocity.newCopy());
744 MFRPtr rNorm = _options.getMomentumLinearSolver().solve(ls);
746 if (!_initialMomentumNorm) _initialMomentumNorm = rNorm;
748 _options.getMomentumLinearSolver().cleanup();
755 _momApField = shared_ptr<Field>(
new Field(
"momAp"));
756 const int numMeshes =
_meshes.size();
757 for (
int n=0; n<numMeshes; n++)
766 _momApField->addArray(cells,dynamic_pointer_cast<ArrayBase>(momAp.
newCopy()));
768 _momApField->syncLocal();
785 const int nFaces = faces.
getCount();
787 for(
int f=0; f<nFaces; f++)
789 int c0 = faceCells(f,0);
790 int c1 = faceCells(f,1);
819 const TArray& pp =
dynamic_cast<const TArray&
>(ppField[pIndex]);
821 const int nFaces = faces.
getCount();
822 for(
int f=0; f<nFaces; f++)
824 const int c0 = faceCells(f,0);
825 const int c1 = faceCells(f,1);
827 const T ppFace = pp[c1];
828 const VectorT3 ppA = ppFace*faceArea[f];
830 V[c0] += ppA/momAp[c0];
839 const TArray& dMassFlux =
dynamic_cast<const TArray&
>(ppField[mfIndex]);
840 TArray& massFlux =
dynamic_cast<TArray&
>(_flowFields.massFlux[faces]);
842 const int nFaces = faces.
getCount();
843 for(
int f=0; f<nFaces; f++)
845 massFlux[f] -= dMassFlux[f];
855 TArray& p =
dynamic_cast<TArray&
>(_flowFields.pressure[cells]);
856 const TArray& pp =
dynamic_cast<const TArray&
>(xField[pIndex]);
858 const T pressureURF(_options[
"pressureURF"]);
861 for(
int c=0; c<nCells; c++)
863 p[c] += pressureURF*(pp[c]-_referencePP);
877 const T velocityURF(_options[
"velocityURF"]);
880 for(
int c=0; c<nCells; c++)
882 V[c] += velocityURF*Vp[c];
892 dynamic_cast<VectorT3Array&
>(_flowFields.momentumFlux[faces]);
896 const int nFaces = faces.
getCount();
897 for(
int f=0; f<nFaces; f++)
899 momFlux[f] += dmomFlux[f];
912 const IntArray& ibType =
dynamic_cast<const IntArray&
>(_geomFields.ibType[cells]);
936 for (
int n = 0; n < nCells; n++ )
941 int glblIndx = localToGlobal[n];
946 if ( glblIndx < _globalRefCellID )
947 _globalRefCellID = glblIndx;
952 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &_globalRefCellID, 1, MPI::INT, MPI::MIN);
955 _globalRefProcID = -1;
958 if ( globalToLocal.count(_globalRefCellID) > 0 ){
959 _globalRefProcID = MPI::COMM_WORLD.Get_rank();
961 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &_globalRefProcID, 1, MPI::INT, MPI::MAX);
964 if ( globalToLocal.count(_globalRefCellID) > 0)
966 int nc = globalToLocal.find(_globalRefCellID)->second;
969 int nc = _globalRefCellID;
974 for(
int nb=row[nc]; nb<row[nc+1]; nb++)
980 dynamic_cast<PVMatrix&
>(mfmatrix.
getMatrix(pIndex,vIndex));
982 PVDiagArray& pvDiag = pvMatrix.getDiag();
983 PVDiagArray& pvCoeff = pvMatrix.getOffDiag();
986 for(
int nb=row[nc]; nb<row[nc+1]; nb++)
1005 this->_useReferencePressure =
true;
1006 const int numMeshes =
_meshes.size();
1011 _flowFields.pressureGradient.syncLocal();
1014 for (
int n=0; n<numMeshes; n++)
1034 interfaceContinuityBC(mesh,faces,matrix,b);
1045 if ((bc.
bcType ==
"NoSlipWall") ||
1046 (bc.
bcType ==
"SlipJump") ||
1047 (bc.
bcType ==
"Symmetry") ||
1048 (bc.
bcType ==
"VelocityBoundary"))
1053 else if (bc.
bcType ==
"PressureBoundary")
1056 this->_useReferencePressure=
false;
1063 FFMatrix& dFluxdFlux =
1064 dynamic_cast<FFMatrix&
>(matrix.
getMatrix(mfIndex,mfIndex));
1070 if (_geomFields.volumeN1.hasArray(cells))
1075 dynamic_cast<const TArray&
>(_flowFields.density[cells]);
1076 const TArray& cellVolume =
1077 dynamic_cast<const TArray&
>(_geomFields.volume[cells]);
1079 T _dT(_options[
"timeStep"]);
1080 T onePointFive(1.5);
1084 const TArray& cellVolumeN1 =
1085 dynamic_cast<const TArray&
>(_geomFields.volumeN1[cells]);
1087 if (_geomFields.volumeN2.hasArray(cells))
1091 const TArray& cellVolumeN2 =
1092 dynamic_cast<const TArray&
>(_geomFields.volumeN2[cells]);
1093 for(
int c=0; c<nCells; c++)
1095 const T rhobydT = density[c]/_dT;
1096 const T term1 = onePointFive*cellVolume[c];
1097 const T term2 = two*cellVolumeN1[c];
1098 const T term3 = pointFive*cellVolumeN2[c];
1099 netFlux -= rhobydT*(term1 - term2 + term3);
1105 for(
int c=0; c<nCells; c++)
1107 const T rhobydT = density[c]/_dT;
1108 netFlux -= rhobydT*(cellVolume[c] - cellVolumeN1[c]);
1117 const int nFaces = faces.
getCount();
1120 dynamic_cast<const VectorT3Array&
>(_geomFields.area[faces]);
1122 dynamic_cast<const VectorT3Array&
>(_geomFields.faceVel[faces]);
1123 for(
int f=0; f<nFaces; f++)
1125 const int c0 = faceCells(f,0);
1126 netFlux += density[c0]*
dot(faceVel[f],faceArea[f]);
1136 MPI::COMM_WORLD.Allreduce( MPI::IN_PLACE, &netFlux, count, MPI::DOUBLE, MPI::SUM);
1138 int useReferencePressureInt = int(this->_useReferencePressure );
1139 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &useReferencePressureInt, count, MPI::INT, MPI::PROD);
1140 this->_useReferencePressure = bool(useReferencePressureInt);
1144 if (this->_useReferencePressure)
1156 for (
int n=0; n<numMeshes; n++)
1160 const IntArray& ibType =
dynamic_cast<const IntArray&
>(_geomFields.ibType[cells]);
1161 const TArray& cellVolume =
dynamic_cast<const TArray&
>(_geomFields.volume[cells]);
1164 volumeSum += cellVolume[c];
1168 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &volumeSum, 1, MPI::DOUBLE, MPI::SUM);
1171 netFlux /= volumeSum;
1173 for (
int n=0; n<numMeshes; n++)
1177 const IntArray& ibType =
dynamic_cast<const IntArray&
>(_geomFields.ibType[cells]);
1178 const TArray& cellVolume =
dynamic_cast<const TArray&
>(_geomFields.volume[cells]);
1186 rCell[c] += netFlux*cellVolume[c];
1195 setDirichlet(matrix,b);
1202 if (_useReferencePressure)
1209 const TArray& pp =
dynamic_cast<const TArray&
>(ppField[pIndex]);
1211 #ifndef FVM_PARALLEL
1212 _referencePP = pp[_globalRefCellID];
1219 if ( MPI::COMM_WORLD.Get_rank() == _globalRefProcID ){
1220 int localID = globalToLocal.find(_globalRefCellID)->second;
1221 _referencePP = pp[localID];
1225 MPI::COMM_WORLD.Bcast( &_referencePP, count, MPI::DOUBLE, _globalRefProcID);
1237 const int numMeshes =
_meshes.size();
1238 for (
int n=0; n<numMeshes; n++)
1245 TArray& r =
dynamic_cast<TArray&
>(_flowFields.continuityResidual[cells]);
1246 const TArray& massFlux =
dynamic_cast<const TArray&
>(_flowFields.massFlux[faces]);
1249 const int nFaces = faces.
getCount();
1252 for(
int f=0; f<nFaces; f++)
1254 const int c0 = faceCells(f,0);
1255 const int c1 = faceCells(f,1);
1257 r[c0] += massFlux[f];
1258 r[c1] -= massFlux[f];
1268 setReferencePP(ppField);
1270 const int numMeshes =
_meshes.size();
1271 for (
int n=0; n<numMeshes; n++)
1281 const bool coupled = matrix.
hasMatrix(pIndex,vIndex);
1283 correctPressure(mesh,ppField);
1290 correctVelocityExplicit(mesh,ppField);
1291 else if (_options.correctVelocity)
1304 correctVelocityExplicit(mesh,ppField);
1305 else if (_options.correctVelocity)
1318 correctMassFluxBoundary(faces,ppField);
1320 if (!coupled && _options.correctVelocity)
1321 correctVelocityBoundary(mesh,faces,ppField);
1323 if (bc.
bcType ==
"PressureBoundary")
1325 T bp = bc[
"specifiedPressure"];
1334 _flowFields.velocity.syncLocal();
1335 _flowFields.pressure.syncLocal();
1337 computeContinuityResidual();
1343 const int numMeshes =
_meshes.size();
1344 for (
int n=0; n<numMeshes; n++)
1351 ls.
getX().
addArray(pIndex,_flowFields.pressure.getArrayPtr(cells));
1365 ls.
getX().
addArray(fIndex,_flowFields.massFlux.getArrayPtr(faces));
1381 ls.
getX().
addArray(fIndex,_flowFields.massFlux.getArrayPtr(faces));
1398 initContinuityLinearization(*ls);
1402 linearizeContinuity(*ls);
1412 shared_ptr<LinearSystem> ls(discretizeContinuity());
1415 _previousVelocity = shared_ptr<Field>();
1417 MFRPtr rNorm = _options.getPressureLinearSolver().solve(*ls);
1419 if (!_initialContinuityNorm) _initialContinuityNorm = rNorm;
1422 _options.pressureLinearSolver->cleanup();
1424 postContinuitySolve(*ls);
1428 _momApField = shared_ptr<Field>();
1436 for(
int n=0; n<niter; n++)
1438 MFRPtr mNorm = solveMomentum();
1439 MFRPtr cNorm = solveContinuity();
1443 _initialMomentumNorm->setMax(*mNorm);
1444 _initialContinuityNorm->setMax(*cNorm);
1447 MFRPtr mNormRatio((*mNorm)/(*_initialMomentumNorm));
1448 MFRPtr cNormRatio((*cNorm)/(*_initialContinuityNorm));
1451 if ( MPI::COMM_WORLD.Get_rank() == 0 ){
1452 if (_options.printNormalizedResiduals)
1453 {cout << _niters <<
": " << *mNormRatio <<
";" << *cNormRatio << endl;}
1455 cout << _niters <<
": " << *mNorm <<
";" << *cNorm << endl;}}
1458 #ifndef FVM_PARALLEL
1459 if (_options.printNormalizedResiduals)
1460 {cout << _niters <<
": " << *mNormRatio <<
";" << *cNormRatio << endl;}
1462 {cout << _niters <<
": " << *mNorm <<
";" << *cNorm << endl;}
1466 if ((*mNormRatio < _options.momentumTolerance) &&
1467 (*cNormRatio < _options.continuityTolerance))
1474 bool advanceCoupled(
const int niter)
1476 const int numMeshes =
_meshes.size();
1477 for(
int n=0; n<niter; n++)
1482 initMomentumLinearization(ls);
1483 initContinuityLinearization(ls);
1485 for (
int n=0; n<numMeshes; n++)
1495 shared_ptr<Matrix> mvp(
new VPMatrix(cellCells));
1498 shared_ptr<Matrix> mpv(
new PVMatrix(cellCells));
1504 linearizeMomentum(ls);
1507 _previousVelocity = dynamic_pointer_cast<
Field>(_flowFields.velocity.newCopy());
1510 _momApField = shared_ptr<Field>(
new Field(
"momAp"));
1511 for (
int n=0; n<numMeshes; n++)
1517 const VVMatrix& vvMatrix =
1519 const VVDiagArray& momAp = vvMatrix.getDiag();
1520 _momApField->addArray(cells,dynamic_pointer_cast<ArrayBase>(momAp.newCopy()));
1523 linearizeContinuity(ls);
1527 MFRPtr rNorm = _options.coupledLinearSolver->solve(ls);
1529 if (!_initialCoupledNorm) _initialCoupledNorm = rNorm;
1533 postContinuitySolve(ls);
1535 _options.coupledLinearSolver->cleanup();
1538 _initialCoupledNorm->setMax(*rNorm);
1540 MFRPtr normRatio((*rNorm)/(*_initialCoupledNorm));
1542 if (_options.printNormalizedResiduals)
1543 cout << _niters <<
": " << *normRatio << endl;
1545 cout << _niters <<
": " << *rNorm << endl;
1549 _momApField = shared_ptr<Field>();
1551 if (*normRatio < _options.momentumTolerance)
1558 #if !(defined(USING_ATYPE_TANGENT) || defined(USING_ATYPE_PC))
1563 shared_ptr<LinearSystem> ls(discretizeContinuity());
1587 int nCoeffs = nCells;
1589 for(
int i=0; i<nCells; i++)
1590 for(
int jp=row[i]; jp<row[i+1]; jp++)
1592 const int j = col[jp];
1593 if (j<nCells) nCoeffs++;
1596 string matFileName = fileBase +
".mat";
1597 FILE *matFile = fopen(matFileName.c_str(),
"wb");
1599 fprintf(matFile,
"%%%%MatrixMarket matrix coordinate real general\n");
1600 fprintf(matFile,
"%d %d %d\n", nCells,nCells,nCoeffs);
1602 for(
int i=0; i<nCells; i++)
1604 fprintf(matFile,
"%d %d %lf\n", i+1, i+1, ppDiag[i]);
1605 for(
int jp=row[i]; jp<row[i+1]; jp++)
1607 const int j = col[jp];
1609 fprintf(matFile,
"%d %d %lf\n", i+1, j+1, ppCoeff[jp]);
1615 string rhsFileName = fileBase +
".rhs";
1616 FILE *rhsFile = fopen(rhsFileName.c_str(),
"wb");
1618 for(
int i=0; i<nCells; i++)
1619 fprintf(rhsFile,
"%lf\n",-rCell[i]);
1627 foreach(
typename FlowBCMap::value_type& pos, _bcMap)
1629 cout <<
"Face Group " << pos.first <<
":" << endl;
1630 cout <<
" bc type " << pos.second->bcType << endl;
1633 cout <<
" " << vp.first <<
" " << vp.second.constant << endl;
1645 if (fg.
id == faceGroupId)
1649 dynamic_cast<const VectorT3Array&
>(_geomFields.area[faces]);
1650 const int nFaces = faces.
getCount();
1651 const TArray& facePressure =
dynamic_cast<const TArray&
>(_flowFields.pressure[faces]);
1652 for(
int f=0; f<nFaces; f++)
1653 r += faceArea[f]*facePressure[f];
1659 throw CException(
"getPressureIntegral: invalid faceGroupID");
1670 const int nibf = ibFaces.
getCount();
1672 const IntArray& ibType =
dynamic_cast<const IntArray&
>(_geomFields.ibType[cells]);
1674 dynamic_cast<const VectorT3Array&
>(_geomFields.area[faces]);
1675 const TArray& facePressure =
dynamic_cast<const TArray&
>(_flowFields.pressure[faces]);
1677 for (
int f = 0; f < nibf; f ++)
1679 const int ibFaceIndex = ibFaceIndices[f];
1680 const int c0 = faceCells(ibFaceIndex,0);
1686 r += faceArea[ibFaceIndex]*facePressure[ibFaceIndex];
1688 r -= faceArea[ibFaceIndex]*facePressure[ibFaceIndex];
1692 MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, r.
getData(), 3, MPI::DOUBLE, MPI::SUM);
1707 if (fg.
id == faceGroupId)
1710 const int nFaces = faces.
getCount();
1712 dynamic_cast<const VectorT3Array&
>(_flowFields.momentumFlux[faces]);
1713 for(
int f=0; f<nFaces; f++)
1719 throw CException(
"getMomentumFluxIntegral: invalid faceGroupID");
1730 dynamic_cast<const TArray&
>(_flowFields.density[cells]);
1732 dynamic_cast<const VectorT3Array&
>(_flowFields.velocity[cells]);
1734 dynamic_cast<const VectorT3Array&
>(_flowFields.velocityN1[cells]);
1737 dynamic_cast<const TArray&
>(_geomFields.volume[cells]);
1739 const T deltaT = _options[
"timeStep"];
1741 if (_flowFields.velocityN2.hasArray(cells))
1745 dynamic_cast<const VectorT3Array&
>(_flowFields.velocityN2[cells]);
1746 T onePointFive(1.5);
1750 for(
int c=0; c<nCells; c++)
1752 const T rhoVbydT = density[c]*volume[c]/deltaT;
1753 r += rhoVbydT*(onePointFive*v[c]- two*vN1[c]
1754 + pointFive*vN2[c]);
1759 for(
int c=0; c<nCells; c++)
1761 const T rhoVbydT = density[c]*volume[c]/deltaT;
1762 r += rhoVbydT*(v[c]- vN1[c]);
1777 _velocityGradientModel.compute();
1780 dynamic_cast<const VGradArray&
>(_flowFields.velocityGradient[cells]);
1783 dynamic_cast<const TArray&
>(_flowFields.pressure[cells]);
1785 const TArray& mu =
dynamic_cast<const TArray&
>(getViscosityField()[cells]);
1787 boost::shared_ptr<StressTensorArray> stressTensorPtr(
new StressTensorArray(nCells));
1788 StressTensorArray& stressTensor = *stressTensorPtr;
1790 for(
int n=0; n<nCells; n++)
1792 const int c = cellIds[n];
1796 for(
int i=0;i<3;i++)
1797 for(
int j=0;j<3;j++)
1798 vgPlusTranspose[i][j] += vg[j][i];
1800 stressTensor[n][0] = vgPlusTranspose[0][0]*mu[c] - pCell[c];
1801 stressTensor[n][1] = vgPlusTranspose[1][1]*mu[c] - pCell[c];
1802 stressTensor[n][2] = vgPlusTranspose[2][2]*mu[c] - pCell[c];
1803 stressTensor[n][3] = vgPlusTranspose[0][1]*mu[c];
1804 stressTensor[n][4] = vgPlusTranspose[1][2]*mu[c];
1805 stressTensor[n][5] = vgPlusTranspose[2][0]*mu[c];
1808 return stressTensorPtr;
1814 const int nSolidFaces = solidFaces.
getCount();
1819 dynamic_cast<VectorT3Array&
>(_flowFields.InterfaceVelocity[solidFaces]);
1821 dynamic_cast<TArray&
>(_flowFields.InterfacePressure[solidFaces]);
1823 dynamic_cast<TArray&
>(_flowFields.InterfaceDensity[solidFaces]);
1826 StressTensorArray& stressTensor =
dynamic_cast<StressTensorArray &
>(_flowFields.InterfaceStress[solidFaces]);
1829 const int numMeshes =
_meshes.size();
1831 for (
int n=0; n<numMeshes; n++)
1837 _velocityGradientModel.compute();
1840 dynamic_cast<VGradArray&
>(_flowFields.velocityGradient[cells]);
1842 dynamic_cast<const TArray&
>(_flowFields.pressure[cells]);
1844 dynamic_cast<const TArray&
>(_flowFields.density[cells]);
1851 for(
int f=0; f<nSolidFaces; f++)
1854 const int c0 = _faceCells(f,0);
1855 const int c1 = _faceCells(f,1);
1861 for(
int i=0;i<3;i++)
1862 for(
int j=0;j<3;j++)
1863 vgPlusTranspose[i][j] += vg[j][i];
1865 stressTensor[f][0] = vgPlusTranspose[0][0];
1866 stressTensor[f][1] = vgPlusTranspose[1][1];
1867 stressTensor[f][3] = vgPlusTranspose[0][1];
1868 stressTensor[f][4] = vgPlusTranspose[1][2];
1869 stressTensor[f][5] = vgPlusTranspose[2][0];
1872 IntDens[f]=dCell[c1];
1873 IntPress[f]=pCell[c1];
1874 IntVel[f][0]=vCell[c1][0];
1875 IntVel[f][1]=vCell[c1][1];
1876 IntVel[f][2]=vCell[c1][2];
1890 shared_ptr<VectorT3Array> tractionXPtr(
new VectorT3Array(nCells));
1891 tractionXPtr->zero();
1892 _flowFields.tractionX.addArray(cells,tractionXPtr);
1895 shared_ptr<VectorT3Array> tractionYPtr(
new VectorT3Array(nCells));
1896 tractionYPtr->zero();
1897 _flowFields.tractionY.addArray(cells,tractionYPtr);
1900 shared_ptr<VectorT3Array> tractionZPtr(
new VectorT3Array(nCells));
1901 tractionZPtr->zero();
1902 _flowFields.tractionZ.addArray(cells,tractionZPtr);
1905 _velocityGradientModel.compute();
1908 dynamic_cast<const VGradArray&
>(_flowFields.velocityGradient[cells]);
1911 dynamic_cast<const TArray&
>(_flowFields.pressure[cells]);
1913 const TArray& mu =
dynamic_cast<const TArray&
>(getViscosityField()[cells]);
1915 for(
int n=0; n<nCells; n++)
1920 for(
int i=0;i<3;i++)
1921 for(
int j=0;j<3;j++)
1922 vgPlusTranspose[i][j] += vg[j][i];
1924 tractionX[n][0] = vgPlusTranspose[0][0]*mu[n] - pCell[n];
1925 tractionX[n][1] = vgPlusTranspose[0][1]*mu[n];
1926 tractionX[n][2] = vgPlusTranspose[0][2]*mu[n];
1928 tractionY[n][0] = vgPlusTranspose[1][0]*mu[n];
1929 tractionY[n][1] = vgPlusTranspose[1][1]*mu[n] - pCell[n];
1930 tractionY[n][2] = vgPlusTranspose[1][2]*mu[n];
1932 tractionZ[n][0] = vgPlusTranspose[2][0]*mu[n];
1933 tractionZ[n][1] = vgPlusTranspose[2][1]*mu[n];
1934 tractionZ[n][2] = vgPlusTranspose[2][2]*mu[n] - pCell[n];
1943 const int nSolidFaces = solidFaces.
getCount();
1945 _velocityGradientModel.compute();
1947 boost::shared_ptr<VectorT3Array>
1952 _flowFields.force.addArray(solidFaces,forcePtr);
1955 dynamic_cast<const VectorT3Array&
>(_geomFields.area[solidFaces]);
1957 const TArray& solidFaceAreaMag =
1958 dynamic_cast<const TArray&
>(_geomFields.areaMag[solidFaces]);
1960 const int numMeshes =
_meshes.size();
1961 for (
int n=0; n<numMeshes; n++)
1966 dynamic_cast<const VGradArray&
>(_flowFields.velocityGradient[cells]);
1969 dynamic_cast<const TArray&
>(_flowFields.pressure[cells]);
1972 dynamic_cast<const TArray&
>(getViscosityField()[cells]);
1983 const IMatrix& mIC =
1984 dynamic_cast<const IMatrix&
>
1985 (*_geomFields._interpolationMatrices[key1]);
1987 const Array<T>& iCoeffs = mIC.getCoeff();
1989 for(
int f=0; f<nSolidFaces; f++)
1992 for(
int nc = sFCRow[f]; nc<sFCRow[f+1]; nc++)
1994 const int c = sFCCol[nc];
1998 for(
int i=0;i<3;i++)
1999 for(
int j=0;j<3;j++)
2000 vgPlusTranspose[i][j] += vg[j][i];
2002 const T coeff = iCoeffs[nc];
2004 stress[0] += coeff*(vgPlusTranspose[0][0]*mu[c] - pCell[c]);
2005 stress[1] += coeff*(vgPlusTranspose[1][1]*mu[c] - pCell[c]);
2006 stress[2] += coeff*(vgPlusTranspose[2][2]*mu[c] - pCell[c]);
2007 stress[3] += coeff*(vgPlusTranspose[0][1]*mu[c]);
2008 stress[4] += coeff*(vgPlusTranspose[1][2]*mu[c]);
2009 stress[5] += coeff*(vgPlusTranspose[2][0]*mu[c]);
2012 const VectorT3& Af = solidFaceArea[f];
2013 force[f][0] = Af[0]*stress[0] + Af[1]*stress[3] + Af[2]*stress[5];
2014 force[f][1] = Af[0]*stress[3] + Af[1]*stress[1] + Af[2]*stress[4];
2015 force[f][2] = Af[0]*stress[5] + Af[1]*stress[4] + Af[2]*stress[2];
2018 force[f] /= solidFaceAreaMag[f];
2031 const int nibf = ibFaces.
getCount();
2033 dynamic_cast<const VectorT3Array&
>(_flowFields.momentumFlux[faces]);
2034 for (
int f = 0; f < nibf; f ++){
2035 const int ibFaceIndex = ibFaceIndices[f];
2036 r += momFlux[ibFaceIndex];
2039 throw CException(
"getMomentumFluxIntegralonIBFaces: no ibFaces found!");
2046 const int numMeshes =
_meshes.size();
2047 for (
int n=0; n<numMeshes; n++)
2058 dynamic_cast<const VectorT3Array&
>(_geomFields.area[faces]);
2059 const int nFaces = faces.
getCount();
2060 const TArray& facePressure =
dynamic_cast<const TArray&
>(_flowFields.pressure[faces]);
2061 for(
int f=0; f<nFaces; f++)
2062 r += faceArea[f]*facePressure[f];
2064 cout <<
"Mesh " << mesh.
getID() <<
" faceGroup " << fg.
id <<
" : " << r << endl;
2071 const int numMeshes =
_meshes.size();
2072 for (
int n=0; n<numMeshes; n++)
2082 const int nFaces = faces.
getCount();
2084 dynamic_cast<const VectorT3Array&
>(_flowFields.momentumFlux[faces]);
2085 for(
int f=0; f<nFaces; f++)
2088 cout <<
"Mesh " << mesh.
getID() <<
" faceGroup " << fg.
id <<
" : " << r << endl;
2095 const int numMeshes =
_meshes.size();
2096 for (
int n=0; n<numMeshes; n++)
2106 const int nFaces = faces.
getCount();
2107 const TArray& massFlux =
dynamic_cast<const TArray&
>(_flowFields.massFlux[faces]);
2108 for(
int f=0; f<nFaces; f++)
2111 cout <<
"Mesh " << mesh.
getID() <<
" faceGroup " << fg.
id <<
" : " << r << endl;
2154 _impl(new
Impl(geomFields,thermalFields,meshes))
2197 return _impl->advance(niter);
2205 return _impl->advanceCoupled(niter);
2214 return _impl->getMomentumSolver();
2221 return _impl->getContinuitySolver();
2229 _impl->updateTime();
2236 _impl->printPressureIntegrals();
2243 _impl->printMomentumFluxIntegrals();
2250 _impl->printMassFluxIntegrals();
2257 return _impl->getPressureIntegral(mesh,faceGroupId);
2264 return _impl->getMomentumFluxIntegral(mesh,faceGroupId);
2271 return _impl->getMomentumDerivativeIntegral(mesh);
2278 return _impl->getPressureIntegralonIBFaces(mesh);
2285 return _impl->getMomentumFluxIntegralonIBFaces(mesh);
2292 return _impl->computeIBFaceVelocity(particles);
2299 return _impl->computeSolidSurfaceForce(particles,
false);
2306 return _impl->computeSolidSurfaceForce(particles,
true);
2311 boost::shared_ptr<ArrayBase>
2314 return _impl->getStressTensor(mesh, cellIds);
2321 return _impl->getTraction(mesh);
2328 return _impl-> ComputeStressTensorES(particles);
2331 map<string,shared_ptr<ArrayBase> >&
2334 return _impl->getPersistenceData();
2347 #if !(defined(USING_ATYPE_TANGENT) || defined(USING_ATYPE_PC))
2352 _impl->dumpContinuityMatrix(fileBase);
void ComputeStressTensorES(const StorageSite &solidFaces)
virtual map< string, shared_ptr< ArrayBase > > & getPersistenceData()
MFRPtr _initialMomentumNorm
void dumpContinuityMatrix(const string fileBase)
const FaceGroupList & getBoundaryFaceGroups() const
const Array< int > & getCol() const
void computeSolidSurfaceForce(const StorageSite &solidFaces, bool perUnitArea)
MFRPtr _initialCoupledNorm
const Array< int > & getRow() const
const FaceGroup & getInteriorFaceGroup() const
bool _useReferencePressure
void getTraction(const Mesh &mesh)
Matrix & getMatrix(const Index &rowIndex, const Index &colIndex)
shared_ptr< FaceGroup > FaceGroupPtr
void getTraction(const Mesh &mesh)
const StorageSite & getIBFaces() const
VectorT3 getPressureIntegralonIBFaces(const Mesh &mesh)
FluxJacobianMatrix< T, T > FMatrix
const CRConnectivity & getConnectivity(const StorageSite &from, const StorageSite &to) const
Gradient< VectorT3 > VGradType
const GeomFields & _geomFields
VectorT3 getMomentumFluxIntegralonIBFaces(const Mesh &mesh)
Array< VectorT3 > VectorT3Array
Vector< T, 3 > getPressureIntegralonIBFaces(const Mesh &mesh)
void printPressureIntegrals()
void fixedPressureMomentumBC(const StorageSite &faces, const Mesh &mesh, MultiFieldMatrix &matrix, const MultiField &xField, MultiField &rField)
void setDirichlet(MultiFieldMatrix &mfmatrix, MultiField &rField)
void printMassFluxIntegrals()
shared_ptr< Field > _momApField
bool hasMatrix(const Index &rowIndex, const Index &colIndex) const
VVMatrix::DiagArray VVDiagArray
map< string, shared_ptr< ArrayBase > > _persistenceData
void correctVelocityBoundary(const Mesh &mesh, const StorageSite &faces, const MultiField &ppField)
const Array< int > & getIBFaceList() const
shared_ptr< LinearSystem > discretizeContinuity()
double max(double x, double y)
FlowModelOptions< T > & getOptions()
VectorT3 getMomentumFluxIntegral(const Mesh &mesh, const int faceGroupId)
Array< Diag > & getDiag()
void updateFacePressureInterior(const Mesh &mesh, const StorageSite &faces, const bool isSymmetry=false)
GradientModel< VectorT3 > _velocityGradientModel
map< int, int > & getGlobalToLocal()
Vector< T, 3 > getPressureIntegral(const Mesh &mesh, const int faceGroupID)
FlowModel(const GeomFields &geomFields, FlowFields &thermalFields, const MeshList &meshes)
void ComputeStressTensorES(const StorageSite &particles)
void printPressureIntegrals()
void postContinuitySolve(LinearSystem &ls)
virtual const CRConnectivity & getConnectivity() const
void correctPressure(const Mesh &mesh, const MultiField &xField)
FloatVal< T > getVal(const string varName) const
MFRPtr _initialContinuityNorm
bool advance(const int niter)
Array< Vector< double, 3 > > VectorT3Array
map< string, shared_ptr< ArrayBase > > & getPersistenceData()
map< string, shared_ptr< ArrayBase > > _persistenceData
void correctVelocityInterior(const Mesh &mesh, const StorageSite &faces, const MultiField &ppField, const bool isSymmetry=false)
void correctMassFluxBoundary(const StorageSite &faces, const MultiField &ppField)
Array< StressTensorT6 > StressTensorArray
Array< OffDiag > & getOffDiag()
const CRConnectivity & getAllFaceCells() const
Vector< T, 3 > getMomentumFluxIntegral(const Mesh &mesh, const int faceGroupID)
T discretizeMassFluxInterior(const Mesh &mesh, const StorageSite &faces, MultiFieldMatrix &mfmatrix, const MultiField &xField, MultiField &rField, const bool isSymmetry=false)
boost::shared_ptr< ArrayBase > getStressTensor(const Mesh &mesh, const ArrayBase &gcellIds)
Array< int > & getLocalToGlobal()
pair< const Field *, const StorageSite * > ArrayIndex
void correctVelocityExplicit(const Mesh &mesh, const MultiField &xField)
CRMatrix< DiagTensorT3, T, VectorT3 > VVMatrix
boost::shared_ptr< ArrayBase > getStressTensor(const Mesh &mesh, const ArrayBase &cellIds)
PPMatrix::DiagArray PPDiagArray
void printMomentumFluxIntegrals()
vector< shared_ptr< Discretization > > DiscrList
void initContinuityLinearization(LinearSystem &ls)
DiagonalTensor< T, 3 > DiagTensorT3
void linearizeMomentum(LinearSystem &ls)
const StorageSite & getFaces() const
const CRConnectivity & getCellCells() const
void setReferencePP(const MultiField &ppField)
const StorageSite & getCells() const
StressTensor< T > StressTensorT6
CRMatrix< T, T, T > PPMatrix
void applyInterfaceBC(const int f) const
void correctMassFluxInterior(const Mesh &mesh, const StorageSite &faces, MultiFieldMatrix &mfmatrix, const MultiField &xField)
void computeSolidSurfaceForcePerUnitArea(const StorageSite &particles)
void computeContinuityResidual()
void computeSolidSurfaceForce(const StorageSite &particles)
int getCountLevel1() const
VectorT3 getPressureIntegral(const Mesh &mesh, const int faceGroupId)
std::map< int, FlowBC< T > * > FlowBCMap
const CRConnectivity & getFaceCells(const StorageSite &site) const
FlowModelOptions< T > _options
void computeIBFaceVelocity(const StorageSite &particles)
void addMatrix(const Index &rowI, const Index &colI, shared_ptr< Matrix > m)
Impl(const GeomFields &geomFields, FlowFields &thermalFields, const MeshList &meshes)
void pressureBoundaryPostContinuitySolve(const StorageSite &faces, const Mesh &mesh, const T bp)
void updateFacePressureBoundary(const Mesh &mesh, const StorageSite &faces)
virtual shared_ptr< IContainer > newCopy() const
void slipJumpMomentumBC(const StorageSite &faces, const Mesh &mesh, GenericBCS< VectorT3, DiagTensorT3, T > &gbc, const T accomodationCoefficient, const FloatValEvaluator< VectorT3 > &bVelocity)
void printMassFluxIntegrals()
VectorTranspose< T, 3 > VectorT3T
Array< Gradient< VectorT3 > > VGradArray
shared_ptr< MultiFieldReduction > MFRPtr
shared_ptr< Field > _previousVelocity
void addArray(const ArrayIndex &aIndex, shared_ptr< ArrayBase > a)
T fixedFluxContinuityBC(const StorageSite &faces, const Mesh &mesh, MultiFieldMatrix &matrix, MultiField &xField, MultiField &rField, const FlowBC< T > &bc)
bool advance(const int niter)
const FaceGroupList & getInterfaceGroups() const
FlowModelOptions< T > & getOptions()
Vector< T, 3 > getMomentumDerivativeIntegral(const Mesh &mesh)
const Field & getViscosityField() const
VectorT3 getMomentumDerivativeIntegral(const Mesh &mesh)
void linearizeContinuity(LinearSystem &ls)
T dot(const Vector< T, 3 > &a, const Vector< T, 3 > &b)
Vector< T, 3 > getMomentumFluxIntegralonIBFaces(const Mesh &mesh)
T fixedPressureContinuityBC(const StorageSite &faces, const Mesh &mesh, MultiFieldMatrix &matrix, const MultiField &xField, MultiField &rField)
Array< PGradType > PGradArray
void computeIBFaceVelocity(const StorageSite &particles)
GradientModel< T > _pressureGradientModel
void dumpContinuityMatrix(const string fileBase)
virtual void linearize(DiscrList &discretizations, const MeshList &meshes, MultiFieldMatrix &matrix, MultiField &x, MultiField &b)
void printMomentumFluxIntegrals()
void initMomentumLinearization(LinearSystem &ls)
pair< const StorageSite *, const StorageSite * > SSPair
MultiFieldMatrix & getMatrix()
vector< Mesh * > MeshList
void interfaceContinuityBC(const Mesh &mesh, const StorageSite &faces, MultiFieldMatrix &matrix, MultiField &rField)
PPMatrix::PairWiseAssembler PPAssembler
std::map< int, FlowVC< T > * > FlowVCMap
void setCoarseningField(const Field &f)