72 _realMeshes(realMeshes),
74 _geomFields(geomFields),
77 _batteryModelFields(
"batteryModel")
80 const int numMeshes =
_meshes.size();
82 for (
int n=0; n<numMeshes; n++)
87 pvc->
vcType =
"dielectric";
88 _pvcMap[mesh.
getID()] = pvc;
106 throw CException(
"ElectricModel: unknown face group type "
111 for (
int n=0; n<numMeshes; n++)
116 _tvcMap[mesh.
getID()] = tvc;
123 _tbcMap[fg.
id] = tbc;
131 else if ((fg.
groupType ==
"velocity-inlet") ||
134 tbc->
bcType =
"SpecifiedTemperature";
137 throw CException(
"ThermalModel: unknown face group type "
142 for (
int m=0; m<_nSpecies; m++)
145 _svcMapVector.push_back(svcmap);
147 _sbcMapVector.push_back(sbcmap);
149 _speciesFieldsVector.push_back(sFields);
151 _initialSpeciesNormVector.push_back(iNorm);
153 _currentSpeciesResidual.push_back(rCurrent);
155 for (
int n=0; n<numMeshes; n++)
161 (*svcmap)[mesh.
getID()] = svc;
168 (*sbcmap)[fg.
id] = sbc;
177 throw CException(
"SpeciesModel: unknown face group type "
186 const int numMeshes =
_meshes.size();
189 for (
int n=0; n<numMeshes; n++)
196 const int nCells = cells.
getCount();
202 cout <<
"Mesh: " << n << endl;
203 for (
int c=0; c<nCells; c++)
205 if (((cellCentroid[c])[2] < -3.33)&&((cellCentroid[c])[2] > -3.34))
206 cout << c <<
": " << (cellCentroid[c])[0] <<
" " << (cellCentroid[c])[1] << endl;
210 shared_ptr<TArray> pCell(
new TArray(nCells));
214 *pCell = pvc[
"initialPotential"];
219 typename BatteryPotentialVCMap::const_iterator posParent = _pvcMap.find(mesh.
getParentMeshID());
220 typename BatteryPotentialVCMap::const_iterator posOther = _pvcMap.find(mesh.
getOtherMeshID());
224 const int NumberOfCells = cells.
getCount();
225 for (
int c=0; c<NumberOfCells; c++)
227 if ((c < NumberOfCells/4)||(c >= 3*NumberOfCells/4))
229 (*pCell)[c] = pvcP[
"initialPotential"];
233 (*pCell)[c] = pvcO[
"initialPotential"];
238 _batteryModelFields.potential.addArray(cells,pCell);
240 if (_options.transient)
245 _batteryModelFields.potentialN1.addArray(cells, dynamic_pointer_cast<ArrayBase>(pCell->newCopy()));
249 shared_ptr<TArray> tCell(
new TArray(nCells));
253 *tCell = tvc[
"initialTemperature"];
258 typename BatteryThermalVCMap::const_iterator posParent = _tvcMap.find(mesh.
getParentMeshID());
259 typename BatteryThermalVCMap::const_iterator posOther = _tvcMap.find(mesh.
getOtherMeshID());
263 const int NumberOfCells = cells.
getCount();
264 for (
int c=0; c<NumberOfCells; c++)
266 if ((c < NumberOfCells/4)||(c >= 3*NumberOfCells/4))
268 (*tCell)[c] = tvcP[
"initialTemperature"];
272 (*tCell)[c] = tvcO[
"initialTemperature"];
277 _batteryModelFields.temperature.addArray(cells,tCell);
279 if (_options.transient)
281 _batteryModelFields.temperatureN1.addArray(cells, dynamic_pointer_cast<ArrayBase>(tCell->newCopy()));
282 if (_options.timeDiscretizationOrder > 1)
283 _batteryModelFields.temperatureN2.addArray(cells, dynamic_pointer_cast<ArrayBase>(tCell->newCopy()));
287 shared_ptr<TArray> condCell(
new TArray(nCells));
288 *condCell = pvc[
"conductivity"];
289 _batteryModelFields.conductivity.addArray(cells,condCell);
292 shared_ptr<TArray> thermCondCell(
new TArray(nCells));
293 *thermCondCell = tvc[
"thermalConductivity"];
294 _batteryModelFields.thermalConductivity.addArray(cells,thermCondCell);
299 _batteryModelFields.speciesGradient.addArray(cells,gradS);
302 shared_ptr<TGradArray> gradp(
new TGradArray(nCells));
304 _batteryModelFields.potential_gradient.addArray(cells,gradp);
307 shared_ptr<TGradArray> gradt(
new TGradArray(nCells));
309 _batteryModelFields.temperatureGradient.addArray(cells,gradt);
312 shared_ptr<TArray> rhoCp(
new TArray(nCells));
313 *rhoCp = tvc[
"density"] * tvc[
"specificHeat"];
314 _batteryModelFields.rhoCp.addArray(cells, rhoCp);
317 shared_ptr<TArray> sCell(
new TArray(nCells));
319 _batteryModelFields.heatSource.addArray(cells,sCell);
329 _batteryModelFields.potential_flux.addArray(faces,pFlux);
339 _batteryModelFields.potential_flux.addArray(faces,pFlux);
351 _batteryModelFields.heatFlux.addArray(faces,tFlux);
361 _batteryModelFields.heatFlux.addArray(faces,tFlux);
365 shared_ptr<TArray> lnLCCell(
new TArray(nCells));
367 _batteryModelFields.lnLithiumConcentration.addArray(cells,lnLCCell);
369 shared_ptr<TGradArray> gradLnLC(
new TGradArray(nCells));
371 _batteryModelFields.lnLithiumConcentrationGradient.addArray(cells,gradLnLC);
374 if (_options.thermalModelPC)
376 shared_ptr<VectorT3Array> pstCell(
new VectorT3Array(nCells));
378 _batteryModelFields.potentialSpeciesTemp.addArray(cells,pstCell);
380 if (_options.transient)
382 _batteryModelFields.potentialSpeciesTempN1.addArray(cells,
383 dynamic_pointer_cast<ArrayBase>(pstCell->newCopy()));
384 if (_options.timeDiscretizationOrder > 1)
387 _batteryModelFields.potentialSpeciesTempN2.addArray(cells,
388 dynamic_pointer_cast<ArrayBase>(pstCell->newCopy()));
394 shared_ptr<VectorT3Array> pstDiffCell(
new VectorT3Array(nCells));
396 _batteryModelFields.potentialSpeciesTempDiffusivity.addArray(cells,pstDiffCell);
401 _batteryModelFields.potentialSpeciesTempGradient.addArray(cells,gradpst);
411 _batteryModelFields.potentialSpeciesTempFlux.addArray(faces,pstFlux);
421 _batteryModelFields.potentialSpeciesTempFlux.addArray(faces,pstFlux);
426 shared_ptr<VectorT2Array> pstCell(
new VectorT2Array(nCells));
428 _batteryModelFields.potentialSpeciesTemp.addArray(cells,pstCell);
430 if (_options.transient)
432 _batteryModelFields.potentialSpeciesTempN1.addArray(cells,
433 dynamic_pointer_cast<ArrayBase>(pstCell->newCopy()));
434 if (_options.timeDiscretizationOrder > 1)
437 _batteryModelFields.potentialSpeciesTempN2.addArray(cells,
438 dynamic_pointer_cast<ArrayBase>(pstCell->newCopy()));
444 shared_ptr<VectorT2Array> pstDiffCell(
new VectorT2Array(nCells));
446 _batteryModelFields.potentialSpeciesTempDiffusivity.addArray(cells,pstDiffCell);
451 _batteryModelFields.potentialSpeciesTempGradient.addArray(cells,gradpst);
461 _batteryModelFields.potentialSpeciesTempFlux.addArray(faces,pstFlux);
471 _batteryModelFields.potentialSpeciesTempFlux.addArray(faces,pstFlux);
476 for (
int m=0; m<_nSpecies; m++)
482 for (
int n=0; n<numMeshes; n++)
489 typename BatterySpeciesVCMap::const_iterator pos = svcmap.find(mesh.
getID());
490 if (pos==svcmap.end())
492 throw CException(
"BatteryModel: Error in Species VC Map");
504 *concCell = svc[
"initialConcentration"];
509 typename BatterySpeciesVCMap::const_iterator posParent = svcmap.find(mesh.
getParentMeshID());
510 typename BatterySpeciesVCMap::const_iterator posOther = svcmap.find(mesh.
getOtherMeshID());
514 const int NumberOfCells = cells.
getCount();
515 for (
int c=0; c<NumberOfCells; c++)
517 if ((c < NumberOfCells/4)||(c >= 3*NumberOfCells/4))
519 (*concCell)[c] = svcP[
"initialConcentration"];
523 (*concCell)[c] = svcO[
"initialConcentration"];
530 if (_options.transient)
533 dynamic_pointer_cast<ArrayBase>(concCell->newCopy()));
534 if (_options.timeDiscretizationOrder > 1)
536 dynamic_pointer_cast<ArrayBase>(concCell->newCopy()));
542 *diffusivityCell = svc[
"massDiffusivity"];
585 _initialPotentialNorm =
MFRPtr();
586 _currentPotentialResidual =
MFRPtr();
587 _initialThermalNorm =
MFRPtr();
588 _currentThermalResidual =
MFRPtr();
589 _initialPCNorm =
MFRPtr();
590 _currentPCResidual =
MFRPtr();
591 _batteryModelFields.conductivity.syncLocal();
592 _batteryModelFields.thermalConductivity.syncLocal();
594 _batteryModelFields.potentialSpeciesTempDiffusivity.syncLocal();
610 const int numMeshes =
_meshes.size();
612 for (
int m=0; m<_nSpecies; m++)
616 for (
int n=0; n<numMeshes; n++)
626 if (_options.timeDiscretizationOrder > 1)
636 for (
int n=0; n<numMeshes; n++)
641 if (_options.thermalModelPC)
644 dynamic_cast<VectorT3Array&
>(_batteryModelFields.potentialSpeciesTemp[cells]);
646 dynamic_cast<VectorT3Array&
>(_batteryModelFields.potentialSpeciesTempN1[cells]);
648 if (_options.timeDiscretizationOrder > 1)
659 dynamic_cast<VectorT2Array&
>(_batteryModelFields.potentialSpeciesTemp[cells]);
661 dynamic_cast<VectorT2Array&
>(_batteryModelFields.potentialSpeciesTempN1[cells]);
663 if (_options.timeDiscretizationOrder > 1)
673 dynamic_cast<TArray&
>(_batteryModelFields.temperature[cells]);
675 dynamic_cast<TArray&
>(_batteryModelFields.temperatureN1[cells]);
677 if (_options.timeDiscretizationOrder > 1)
680 dynamic_cast<TArray&
>(_batteryModelFields.temperatureN2[cells]);
687 dynamic_cast<TArray&
>(_batteryModelFields.potential[cells]);
689 dynamic_cast<TArray&
>(_batteryModelFields.potentialN1[cells]);
690 potentialN1 = potential;
697 const int numMeshes =
_meshes.size();
699 for (
int m=0; m<_nSpecies; m++)
703 for (
int n=0; n<numMeshes; n++)
724 for (
int n=0; n<numMeshes; n++)
729 if (_options.thermalModelPC)
732 dynamic_cast<VectorT3Array&
>(_batteryModelFields.potentialSpeciesTemp[cells]);
734 dynamic_cast<VectorT3Array&
>(_batteryModelFields.potentialSpeciesTempN1[cells]);
746 dynamic_cast<VectorT2Array&
>(_batteryModelFields.potentialSpeciesTemp[cells]);
748 dynamic_cast<VectorT2Array&
>(_batteryModelFields.potentialSpeciesTempN1[cells]);
758 dynamic_cast<TArray&
>(_batteryModelFields.temperature[cells]);
760 dynamic_cast<TArray&
>(_batteryModelFields.temperatureN1[cells]);
771 dynamic_cast<TArray&
>(_batteryModelFields.potential[cells]);
773 dynamic_cast<TArray&
>(_batteryModelFields.potentialN1[cells]);
774 potential = potentialN1;
781 const int numMeshes =
_meshes.size();
783 for (
int n=0; n<numMeshes; n++)
885 const int numMeshes =
_meshes.size();
887 for (
int n=0; n<numMeshes; n++)
897 ls.
getX().
addArray(tIndex,_batteryModelFields.potentialSpeciesTemp.getArrayPtr(cells));
901 if (_options.thermalModelPC)
913 ls.
getX().
addArray(fIndex,_batteryModelFields.potentialSpeciesTempFlux.getArrayPtr(faces));
930 ls.
getX().
addArray(fIndex,_batteryModelFields.potentialSpeciesTempFlux.getArrayPtr(faces));
953 ls.
getX().
addArray(fIndex,_batteryModelFields.potentialSpeciesTempFlux.getArrayPtr(faces));
970 ls.
getX().
addArray(fIndex,_batteryModelFields.potentialSpeciesTempFlux.getArrayPtr(faces));
987 ls.
getX().
addArray(tIndex,_batteryModelFields.potentialSpeciesTemp.getArrayPtr(cells));
991 if (_options.thermalModelPC)
1003 ls.
getX().
addArray(fIndex,_batteryModelFields.potentialSpeciesTempFlux.getArrayPtr(faces));
1020 ls.
getX().
addArray(fIndex,_batteryModelFields.potentialSpeciesTempFlux.getArrayPtr(faces));
1043 ls.
getX().
addArray(fIndex,_batteryModelFields.potentialSpeciesTempFlux.getArrayPtr(faces));
1060 ls.
getX().
addArray(fIndex,_batteryModelFields.potentialSpeciesTempFlux.getArrayPtr(faces));
1078 const int numMeshes =
_meshes.size();
1079 for (
int n=0; n<numMeshes; n++)
1086 ls.
getX().
addArray(tIndex,_batteryModelFields.potential.getArrayPtr(cells));
1100 ls.
getX().
addArray(fIndex,_batteryModelFields.potential_flux.getArrayPtr(faces));
1117 ls.
getX().
addArray(fIndex,_batteryModelFields.potential_flux.getArrayPtr(faces));
1133 const int numMeshes =
_meshes.size();
1134 for (
int n=0; n<numMeshes; n++)
1141 ls.
getX().
addArray(tIndex,_batteryModelFields.temperature.getArrayPtr(cells));
1155 ls.
getX().
addArray(fIndex,_batteryModelFields.heatFlux.getArrayPtr(faces));
1172 ls.
getX().
addArray(fIndex,_batteryModelFields.heatFlux.getArrayPtr(faces));
1204 _batteryModelFields.speciesGradient,_geomFields);
1205 speciesGradientModel.
compute();
1238 shared_ptr<Discretization>
1240 (_realMeshes,_geomFields,
1243 _batteryModelFields.speciesGradient));
1244 discretizations.push_back(dd);
1246 if (_options.transient)
1248 shared_ptr<Discretization>
1250 (_realMeshes,_geomFields,
1255 _options[
"timeStep"]));
1257 discretizations.push_back(td);
1266 const int numMeshes =
_meshes.size();
1270 for (
int n=0; n<numMeshes; n++)
1280 if (_options.ButlerVolmer)
1282 bool Cathode =
false;
1284 if (n == _options[
"ButlerVolmerCathodeShellMeshID"])
1288 else if (n == _options[
"ButlerVolmerAnodeShellMeshID"])
1294 _options[
"ButlerVolmerRRConstant"],
1295 _options[
"interfaceSpeciesUnderRelax"],
1300 _batteryModelFields.potential,
1301 _batteryModelFields.temperature);
1348 const int numRealMeshes = _realMeshes.size();
1349 for (
int n=0; n<numRealMeshes; n++)
1358 typename BatterySpeciesBCMap::const_iterator pos = sbcmap.find(fg.
id);
1359 if (pos==sbcmap.end())
1361 throw CException(
"BatteryModel: Error in Species BC Map");
1372 if (bc.
bcType ==
"SpecifiedConcentration")
1375 bT(bc.
getVal(
"specifiedConcentration"),faces);
1378 const TArray& convectingFlux =
1379 dynamic_cast<const TArray&
>
1381 const int nFaces = faces.
getCount();
1383 for(
int f=0; f<nFaces; f++)
1385 if (convectingFlux[f] > 0.)
1387 gbc.applyExtrapolationBC(f);
1391 gbc.applyDirichletBC(f,bT[f]);
1396 gbc.applyDirichletBC(bT);
1398 else if (bc.
bcType ==
"SpecifiedMassFlux")
1400 const T specifiedFlux(bc[
"specifiedMassFlux"]);
1401 gbc.applyNeumannBC(specifiedFlux);
1403 else if ((bc.
bcType ==
"Symmetry"))
1406 gbc.applyNeumannBC(zeroFlux);
1409 throw CException(bc.
bcType +
" not implemented for Species in BatteryModel");
1431 const int numMeshes =
_meshes.size();
1434 _batteryModelFields.potential_gradient,_geomFields);
1435 potentialGradientModel.
compute();
1439 shared_ptr<Discretization>
1441 _batteryModelFields.potential,
1442 _batteryModelFields.conductivity,
1443 _batteryModelFields.potential_gradient));
1444 discretizations.push_back(dd);
1446 if(_options.ButlerVolmer)
1448 bool foundElectrolyte =
false;
1450 for (
int n=0; n<numMeshes; n++)
1452 if (n==_options[
"BatteryElectrolyteMeshID"])
1454 foundElectrolyte =
true;
1459 TArray& lnSpeciesConc =
dynamic_cast<TArray&
>(_batteryModelFields.lnLithiumConcentration[cells]);
1460 for (
int c=0; c<cells.
getCount(); c++)
1462 T CellConc = speciesConc[c];
1463 if (CellConc <= 0.0)
1465 cout <<
"Error: Cell Concentration <= 0 MeshID: " << n <<
" CellNum: " << c << endl;
1468 lnSpeciesConc[c] = log(CellConc);
1473 if ((!(foundElectrolyte))&&(_options.ButlerVolmer))
1474 cout <<
"Warning: Electrolyte Mesh ID not set." << endl;
1478 _batteryModelFields.lnLithiumConcentrationGradient,_geomFields);
1479 lnSpeciesGradientModel.
compute();
1482 shared_ptr<Discretization>
1484 _batteryModelFields.potential,
1485 _batteryModelFields.conductivity,
1486 _batteryModelFields.lnLithiumConcentration,
1487 _batteryModelFields.lnLithiumConcentrationGradient,
1488 _batteryModelFields.temperature,
1489 _options[
"BatteryElectrolyteMeshID"]));
1490 discretizations.push_back(bedd);
1506 for (
int n=0; n<numMeshes; n++)
1516 if (_options.ButlerVolmer)
1518 bool Cathode =
false;
1520 if (n == _options[
"ButlerVolmerCathodeShellMeshID"])
1524 else if (n == _options[
"ButlerVolmerAnodeShellMeshID"])
1531 _batteryModelFields.potential,
1533 _batteryModelFields.temperature,
1534 _options[
"ButlerVolmerRRConstant"],
1545 _batteryModelFields.potential);
1554 for (
int n=0; n<numMeshes; n++)
1562 const int nFaces = faces.
getCount();
1568 _batteryModelFields.potential,
1569 _batteryModelFields.potential_flux,
1572 if (bc.
bcType ==
"SpecifiedPotential")
1575 for(
int f=0; f<nFaces; f++)
1577 gbc.applyDirichletBC(f, bT[f]);
1580 else if (bc.
bcType ==
"SpecifiedPotentialFlux")
1582 const T specifiedFlux(bc[
"specifiedPotentialFlux"]);
1583 gbc.applyNeumannBC(specifiedFlux);
1585 else if (bc.
bcType ==
"Symmetry")
1588 gbc.applyNeumannBC(zeroFlux);
1591 throw CException(bc.
bcType +
" not implemented for Potential in BatteryModel");
1603 _batteryModelFields.potential,
1604 _batteryModelFields.potential_flux,
1615 const int numMeshes =
_meshes.size();
1619 _batteryModelFields.temperatureGradient,_geomFields);
1620 thermalGradientModel.
compute();
1624 _batteryModelFields.potential_gradient,_geomFields);
1625 potentialGradientModel.
compute();
1629 _batteryModelFields.speciesGradient,_geomFields);
1630 speciesGradientModel.
compute();
1634 for (
int n=0; n<numMeshes; n++)
1640 typename BatterySpeciesVCMap::const_iterator pos = svcmap.find(n);
1641 if (pos==svcmap.end())
1643 throw CException(
"BatteryModel: Error in Species VC Map");
1646 const T massDiffusivity = svc[
"massDiffusivity"];
1648 const TGradArray& potentialGradCell =
dynamic_cast<const TGradArray&
>(_batteryModelFields.potential_gradient[cells]);
1649 const TGradArray& speciesGradCell =
dynamic_cast<const TGradArray&
>(_batteryModelFields.speciesGradient[cells]);
1650 TArray& heatSource =
dynamic_cast<TArray&
>(_batteryModelFields.heatSource[cells]);
1651 for (
int c=0; c<cells.
getCount(); c++)
1653 const TGradType pGrad = potentialGradCell[c];
1654 const TGradType sGrad = speciesGradCell[c];
1655 T CellSource = pGrad[0]*sGrad[0] + pGrad[1]*sGrad[1];
1656 if ((*
_meshes[0]).getDimension() == 3)
1657 CellSource += pGrad[2]*sGrad[2];
1659 heatSource[c] = CellSource*massDiffusivity*96485.0;
1665 shared_ptr<Discretization>
1667 _batteryModelFields.temperature,
1668 _batteryModelFields.thermalConductivity,
1669 _batteryModelFields.temperatureGradient));
1670 discretizations.push_back(dd);
1672 if (_options.transient)
1674 shared_ptr<Discretization>
1677 _batteryModelFields.temperature,
1678 _batteryModelFields.temperatureN1,
1679 _batteryModelFields.temperatureN2,
1680 _batteryModelFields.rhoCp,
1681 _options[
"timeStep"]));
1683 discretizations.push_back(td);
1686 shared_ptr<Discretization>
1690 _batteryModelFields.temperature,
1691 _batteryModelFields.heatSource));
1692 discretizations.push_back(sd);
1705 for (
int n=0; n<numMeshes; n++)
1715 if (_options.ButlerVolmer)
1718 bool Cathode =
false;
1720 if (n == _options[
"ButlerVolmerCathodeShellMeshID"])
1724 else if (n == _options[
"ButlerVolmerAnodeShellMeshID"])
1731 _batteryModelFields.temperature,
1733 _batteryModelFields.potential,
1734 _options[
"ButlerVolmerRRConstant"],
1746 _batteryModelFields.temperature);
1755 for (
int n=0; n<numMeshes; n++)
1763 const int nFaces = faces.
getCount();
1769 _batteryModelFields.temperature,
1770 _batteryModelFields.heatFlux,
1773 if (bc.
bcType ==
"SpecifiedTemperature")
1776 for(
int f=0; f<nFaces; f++)
1778 gbc.applyDirichletBC(f, bT[f]);
1781 else if (bc.
bcType ==
"SpecifiedHeatFlux")
1783 const T specifiedFlux(bc[
"specifiedHeatFlux"]);
1784 gbc.applyNeumannBC(specifiedFlux);
1786 else if (bc.
bcType ==
"Symmetry")
1789 gbc.applyNeumannBC(zeroFlux);
1792 throw CException(bc.
bcType +
" not implemented for Thermal in BatteryModel");
1804 _batteryModelFields.temperature,
1805 _batteryModelFields.heatFlux,
1823 _batteryModelFields.potentialSpeciesTempGradient,_geomFields);
1827 bool foundElectrolyte =
false;
1829 const int numMeshes =
_meshes.size();
1830 for (
int n=0; n<numMeshes; n++)
1832 if (n==_options[
"BatteryElectrolyteMeshID"])
1834 foundElectrolyte =
true;
1837 const VectorT3Array& speciesPotentialTemp =
dynamic_cast<const VectorT3Array&
>(_batteryModelFields.potentialSpeciesTemp[cells]);
1838 TArray& lnSpeciesConc =
dynamic_cast<TArray&
>(_batteryModelFields.lnLithiumConcentration[cells]);
1839 for (
int c=0; c<cells.
getCount(); c++)
1841 T CellConc = (speciesPotentialTemp[c])[1];
1842 if (CellConc <= 0.0)
1844 cout <<
"Error: Cell Concentration <= 0 MeshID: " << n <<
" CellNum: " << c << endl;
1847 lnSpeciesConc[c] = log(CellConc);
1852 if ((!(foundElectrolyte))&&(_options.ButlerVolmer))
1853 cout <<
"Warning: Electrolyte Mesh ID not set." << endl;
1857 _batteryModelFields.lnLithiumConcentrationGradient,_geomFields);
1858 lnSpeciesGradientModel.
compute();
1861 for (
int n=0; n<numMeshes; n++)
1866 typename BatterySpeciesVCMap::const_iterator pos = svcmap.find(n);
1867 if (pos==svcmap.end())
1869 throw CException(
"BatteryModel: Error in Species VC Map");
1872 const T massDiffusivity = svc[
"massDiffusivity"];
1875 TArray& heatSource =
dynamic_cast<TArray&
>(_batteryModelFields.heatSource[cells]);
1876 for (
int c=0; c<cells.
getCount(); c++)
1878 const VectorT3Grad combinedCellGradient = pstGradCell[c];
1881 pGrad[0] = combinedCellGradient[0][0];
1882 pGrad[1] = combinedCellGradient[1][0];
1883 sGrad[0] = combinedCellGradient[0][1];
1884 sGrad[1] = combinedCellGradient[1][1];
1885 T CellSource = pGrad[0]*sGrad[0] + pGrad[1]*sGrad[1];
1886 if ((*
_meshes[0]).getDimension() == 3)
1888 pGrad[2] = combinedCellGradient[2][0];
1889 sGrad[2] = combinedCellGradient[2][1];
1890 CellSource += pGrad[2]*sGrad[2];
1892 heatSource[c] = CellSource*massDiffusivity*96485.0;
1899 shared_ptr<Discretization>
1901 (_realMeshes,_geomFields,
1902 _batteryModelFields.potentialSpeciesTemp,
1903 _batteryModelFields.potentialSpeciesTempDiffusivity,
1904 _batteryModelFields.potentialSpeciesTempGradient));
1905 discretizations.push_back(dd);
1908 shared_ptr<Discretization>
1910 _batteryModelFields.potentialSpeciesTemp,
1911 _batteryModelFields.potentialSpeciesTempDiffusivity,
1912 _batteryModelFields.lnLithiumConcentration,
1913 _batteryModelFields.lnLithiumConcentrationGradient,
1914 _options.thermalModelPC,
1915 _options[
"BatteryElectrolyteMeshID"]));
1916 discretizations.push_back(bedd);
1918 if (_options.transient)
1920 shared_ptr<Discretization>
1922 (_realMeshes,_geomFields,
1923 _batteryModelFields.potentialSpeciesTemp,
1924 _batteryModelFields.potentialSpeciesTempN1,
1925 _batteryModelFields.potentialSpeciesTempN2,
1926 _batteryModelFields.rhoCp,
1927 _options.thermalModelPC,
1928 _options[
"timeStep"]));
1930 discretizations.push_back(td);
1935 shared_ptr<Discretization>
1937 (_realMeshes,_geomFields,
1938 _batteryModelFields.potentialSpeciesTemp,
1939 _batteryModelFields.heatSource));
1941 discretizations.push_back(sd);
1951 for (
int n=0; n<numMeshes; n++)
1961 if (_options.ButlerVolmer)
1963 bool Cathode =
false;
1965 if (n == _options[
"ButlerVolmerCathodeShellMeshID"])
1969 else if (n == _options[
"ButlerVolmerAnodeShellMeshID"])
1975 _options[
"ButlerVolmerRRConstant"],
1976 _options[
"interfaceSpeciesUnderRelax"],
1979 _options.thermalModelPC,
1980 _batteryModelFields.potentialSpeciesTemp);
1989 _batteryModelFields.potentialSpeciesTemp);
1998 for (
int n=0; n<numMeshes; n++)
2007 typename BatterySpeciesBCMap::const_iterator pos = sbcmap.find(fg.
id);
2008 if (pos==sbcmap.end())
2010 throw CException(
"BatteryModel: Error in Species BC Map");
2021 _batteryModelFields.potentialSpeciesTemp,
2022 _batteryModelFields.potentialSpeciesTempFlux,
2025 if (sbc.
bcType ==
"SpecifiedConcentration")
2028 sbT(sbc.
getVal(
"specifiedConcentration"),faces);
2030 bbc.applySingleEquationDirichletBC(sbT,1);
2032 else if (sbc.
bcType ==
"SpecifiedMassFlux")
2034 const T specifiedFlux(sbc[
"specifiedMassFlux"]);
2035 bbc.applySingleEquationNeumannBC(specifiedFlux,1);
2037 else if ((sbc.
bcType ==
"Symmetry"))
2040 bbc.applySingleEquationNeumannBC(zeroFlux,1);
2043 throw CException(sbc.
bcType +
" not implemented for Species in BatteryModel");
2045 if (pbc.
bcType ==
"SpecifiedPotential")
2049 bbc.applySingleEquationDirichletBC(pbT,0);
2051 else if (pbc.
bcType ==
"SpecifiedPotentialFlux")
2053 const T specifiedFlux(pbc[
"specifiedPotentialFlux"]);
2054 bbc.applySingleEquationNeumannBC(specifiedFlux,0);
2056 else if ((pbc.
bcType ==
"Symmetry"))
2059 bbc.applySingleEquationNeumannBC(zeroFlux,0);
2062 throw CException(pbc.
bcType +
" not implemented for potential in BatteryModel");
2064 if (tbc.
bcType ==
"SpecifiedTemperature")
2068 bbc.applySingleEquationDirichletBC(tbT,2);
2070 else if (tbc.
bcType ==
"SpecifiedHeatFlux")
2072 const T specifiedFlux(tbc[
"specifiedHeatFlux"]);
2073 bbc.applySingleEquationNeumannBC(specifiedFlux,2);
2075 else if ((tbc.
bcType ==
"Symmetry"))
2078 bbc.applySingleEquationNeumannBC(zeroFlux,2);
2081 throw CException(tbc.
bcType +
" not implemented for temperature in BatteryModel");
2093 _batteryModelFields.potentialSpeciesTemp,
2094 _batteryModelFields.potentialSpeciesTempFlux,
2108 _batteryModelFields.potentialSpeciesTemp,
2109 _batteryModelFields.potentialSpeciesTempFlux,
2141 _batteryModelFields.potentialSpeciesTempGradient,_geomFields);
2145 bool foundElectrolyte =
false;
2147 const int numMeshes =
_meshes.size();
2148 for (
int n=0; n<numMeshes; n++)
2150 if (n==_options[
"BatteryElectrolyteMeshID"])
2152 foundElectrolyte =
true;
2155 const VectorT2Array& speciesPotentialTemp =
dynamic_cast<const VectorT2Array&
>(_batteryModelFields.potentialSpeciesTemp[cells]);
2156 TArray& lnSpeciesConc =
dynamic_cast<TArray&
>(_batteryModelFields.lnLithiumConcentration[cells]);
2157 for (
int c=0; c<cells.
getCount(); c++)
2159 T CellConc = (speciesPotentialTemp[c])[1];
2160 if (CellConc <= 0.0)
2162 cout <<
"Error: Cell Concentration <= 0 MeshID: " << n <<
" CellNum: " << c << endl;
2165 lnSpeciesConc[c] = log(CellConc);
2170 if ((!(foundElectrolyte))&&(_options.ButlerVolmer))
2171 cout <<
"Warning: Electrolyte Mesh ID not set." << endl;
2175 _batteryModelFields.lnLithiumConcentrationGradient,_geomFields);
2176 lnSpeciesGradientModel.
compute();
2181 shared_ptr<Discretization>
2183 (_realMeshes,_geomFields,
2184 _batteryModelFields.potentialSpeciesTemp,
2185 _batteryModelFields.potentialSpeciesTempDiffusivity,
2186 _batteryModelFields.potentialSpeciesTempGradient));
2187 discretizations.push_back(dd);
2190 shared_ptr<Discretization>
2192 _batteryModelFields.potentialSpeciesTemp,
2193 _batteryModelFields.potentialSpeciesTempDiffusivity,
2194 _batteryModelFields.lnLithiumConcentration,
2195 _batteryModelFields.lnLithiumConcentrationGradient,
2196 _options.thermalModelPC,
2197 _options[
"BatteryElectrolyteMeshID"]));
2198 discretizations.push_back(bedd);
2200 if (_options.transient)
2202 shared_ptr<Discretization>
2204 (_realMeshes,_geomFields,
2205 _batteryModelFields.potentialSpeciesTemp,
2206 _batteryModelFields.potentialSpeciesTempN1,
2207 _batteryModelFields.potentialSpeciesTempN2,
2208 _batteryModelFields.rhoCp,
2209 _options.thermalModelPC,
2210 _options[
"timeStep"]));
2212 discretizations.push_back(td);
2222 for (
int n=0; n<numMeshes; n++)
2232 if (_options.ButlerVolmer)
2234 bool Cathode =
false;
2236 if (n == _options[
"ButlerVolmerCathodeShellMeshID"])
2240 else if (n == _options[
"ButlerVolmerAnodeShellMeshID"])
2246 _options[
"ButlerVolmerRRConstant"],
2247 _options[
"interfaceSpeciesUnderRelax"],
2250 _options.thermalModelPC,
2251 _batteryModelFields.potentialSpeciesTemp);
2260 _batteryModelFields.potentialSpeciesTemp);
2269 for (
int n=0; n<numMeshes; n++)
2278 typename BatterySpeciesBCMap::const_iterator pos = sbcmap.find(fg.
id);
2279 if (pos==sbcmap.end())
2281 throw CException(
"BatteryModel: Error in Species BC Map");
2290 _batteryModelFields.potentialSpeciesTemp,
2291 _batteryModelFields.potentialSpeciesTempFlux,
2294 if (sbc.
bcType ==
"SpecifiedConcentration")
2297 sbT(sbc.
getVal(
"specifiedConcentration"),faces);
2299 bbc.applySingleEquationDirichletBC(sbT,1);
2301 else if (sbc.
bcType ==
"SpecifiedMassFlux")
2303 const T specifiedFlux(sbc[
"specifiedMassFlux"]);
2304 bbc.applySingleEquationNeumannBC(specifiedFlux,1);
2306 else if ((sbc.
bcType ==
"Symmetry"))
2309 bbc.applySingleEquationNeumannBC(zeroFlux,1);
2312 throw CException(sbc.
bcType +
" not implemented for Species in BatteryModel");
2314 if (pbc.
bcType ==
"SpecifiedPotential")
2318 bbc.applySingleEquationDirichletBC(pbT,0);
2320 else if (pbc.
bcType ==
"SpecifiedPotentialFlux")
2322 const T specifiedFlux(pbc[
"specifiedPotentialFlux"]);
2323 bbc.applySingleEquationNeumannBC(specifiedFlux,0);
2325 else if ((pbc.
bcType ==
"Symmetry"))
2328 bbc.applySingleEquationNeumannBC(zeroFlux,0);
2331 throw CException(pbc.
bcType +
" not implemented for potential in BatteryModel");
2343 _batteryModelFields.potentialSpeciesTemp,
2344 _batteryModelFields.potentialSpeciesTempFlux,
2358 _batteryModelFields.potentialSpeciesTemp,
2359 _batteryModelFields.potentialSpeciesTempFlux,
2378 if (fg.
id == faceGroupId)
2381 const int nFaces = faces.
getCount();
2384 for(
int f=0; f<nFaces; f++)
2393 if (fg.
id == faceGroupId)
2396 const int nFaces = faces.
getCount();
2399 for(
int f=0; f<nFaces; f++)
2407 throw CException(
"getMassFluxIntegral: invalid faceGroupID");
2419 if (fg.
id == faceGroupId)
2422 const int nFaces = faces.
getCount();
2423 const TArray& potentialFlux =
2424 dynamic_cast<const TArray&
>(_batteryModelFields.potential_flux[faces]);
2425 for(
int f=0; f<nFaces; f++)
2426 r += potentialFlux[f];
2434 if (fg.
id == faceGroupId)
2437 const int nFaces = faces.
getCount();
2438 const TArray& potentialFlux =
2439 dynamic_cast<const TArray&
>(_batteryModelFields.potential_flux[faces]);
2440 for(
int f=0; f<nFaces; f++)
2441 r += potentialFlux[f];
2448 throw CException(
"getPotentialFluxIntegral: invalid faceGroupID");
2460 if (fg.
id == faceGroupId)
2463 const int nFaces = faces.
getCount();
2465 dynamic_cast<const TArray&
>(_batteryModelFields.heatFlux[faces]);
2466 for(
int f=0; f<nFaces; f++)
2475 if (fg.
id == faceGroupId)
2478 const int nFaces = faces.
getCount();
2480 dynamic_cast<const TArray&
>(_batteryModelFields.heatFlux[faces]);
2481 for(
int f=0; f<nFaces; f++)
2489 throw CException(
"getPotentialFluxIntegral: invalid faceGroupID");
2498 const TArray& cellVolume =
dynamic_cast<const TArray&
>(_geomFields.volume[cells]);
2499 T totalVolume = 0.0;
2500 T weightedConcentration = 0.0;
2503 totalVolume += cellVolume[c];
2504 weightedConcentration += concCell[c]*cellVolume[c];
2506 return weightedConcentration/totalVolume;
2516 const int nFaces = faces.
getCount();
2525 TArray& rCell =
dynamic_cast<TArray&
>(rField[cVarIndex]);
2526 TArray& xCell =
dynamic_cast<TArray&
>(xField[cVarIndex]);
2529 for(
int f=0; f<nFaces; f++)
2531 const int c0 = faceCells(f,0);
2532 const int c1 = faceCells(f,1);
2533 T& offdiagC0_C1 = matrix.
getCoeff(c0, c1);
2534 T& offdiagC1_C0 = matrix.
getCoeff(c1, c0);
2535 const T rC0= rCell[c0];
2536 const T rC1= rCell[c1];
2537 const T diagC0= diag[c0];
2538 const T diagC1= diag[c1];
2539 const T xC0 = xCell[c0];
2540 const T xC1 = xCell[c1];
2544 cout <<
"--------------" << endl;
2545 cout << mesh.
getID() <<
":" << f << endl;
2546 cout << offdiagC0_C1 << endl;
2547 cout << offdiagC1_C0 << endl;
2548 cout << rC0 << endl;
2549 cout << rC1 << endl;
2550 cout << diagC0 << endl;
2551 cout << diagC1 << endl;
2552 cout << xC0 << endl;
2553 cout << xC1 << endl;
2555 cout <<
"--------------" << endl;
2640 for(
int n=0; n<niter; n++)
2642 bool allConverged=
true;
2643 for (
int m=0; m<_nSpecies; m++)
2645 MFRPtr& iNorm = *_initialSpeciesNormVector[m];
2646 MFRPtr& rCurrent = *_currentSpeciesResidual[m];
2651 initSpeciesLinearization(ls, lsShell, m);
2657 linearizeSpecies(ls, lsShell, m);
2668 MFRPtr rNorm(_options.getLinearSolverSpecies().solve(ls));
2670 if (!iNorm) iNorm = rNorm;
2671 MFRPtr normRatio((*rNorm)/(*iNorm));
2674 if (((_niters+1) % _options.advanceVerbosity)==0)
2675 cout << _niters <<
": " << *rNorm << endl;
2677 _options.getLinearSolverSpecies().cleanup();
2689 MFRPtr rNorm2(_options.getLinearSolverSpecies().solve(lsShell));
2690 _options.getLinearSolverSpecies().cleanup();
2693 cout << _niters <<
": " << *rNorm2 << endl;
2701 if (!(*rNorm < _options.absoluteSpeciesTolerance ||
2702 *normRatio < _options.relativeSpeciesTolerance))
2712 for(
int n=0; n<niter; n++)
2716 initPotentialLinearization(ls);
2720 linearizePotential(ls);
2724 MFRPtr rNorm(_options.getLinearSolverPotential().solve(ls));
2726 if (!_initialPotentialNorm) _initialPotentialNorm = rNorm;
2728 _currentPotentialResidual = rNorm;
2730 MFRPtr normRatio((*rNorm)/(*_initialPotentialNorm));
2732 if ((_niters % _options.advanceVerbosity)==0)
2733 cout <<
"Potential: " << _niters <<
": " << *rNorm << endl;
2735 _options.getLinearSolverPotential().cleanup();
2742 if (*rNorm < _options.absolutePotentialTolerance ||
2743 *normRatio < _options.relativePotentialTolerance)
2750 for(
int n=0; n<niter; n++)
2754 initThermalLinearization(ls);
2758 linearizeThermal(ls);
2762 MFRPtr rNorm(_options.getLinearSolverThermal().solve(ls));
2764 if (!_initialThermalNorm) _initialThermalNorm = rNorm;
2766 _currentThermalResidual = rNorm;
2768 MFRPtr normRatio((*rNorm)/(*_initialThermalNorm));
2770 if ((_niters % _options.advanceVerbosity)==0)
2771 cout <<
"Thermal: " << _niters <<
": " << *rNorm << endl;
2773 _options.getLinearSolverThermal().cleanup();
2780 if (*rNorm < _options.absoluteThermalTolerance ||
2781 *normRatio < _options.relativeThermalTolerance)
2788 for(
int n=0; n<niter; n++)
2793 initPCLinearization(ls);
2797 if (_options.thermalModelPC)
2798 linearizePC_Thermal(ls);
2804 MFRPtr rNorm = _options.getLinearSolverPC().solve(ls);
2806 if (!_initialPCNorm) _initialPCNorm = rNorm;
2808 _currentPCResidual = rNorm;
2810 MFRPtr normRatio((*rNorm)/(*_initialPCNorm));
2812 _options.getLinearSolverPC().cleanup();
2818 if ((_niters % _options.advanceVerbosity)==0)
2819 cout <<
"Point-Coupled: " << _niters <<
": " << *rNorm << endl;
2823 if (*rNorm < _options.absolutePCTolerance ||
2824 *normRatio < _options.relativePCTolerance)
2831 MFRPtr& rCurrent = *_currentSpeciesResidual[speciesId];
2834 ArrayBase& residualArray = (*rCurrent)[concentrationField];
2835 T *arrayData = (T*)(residualArray.
getData());
2836 const T residual = arrayData[0];
2842 const Field& potentialField = _batteryModelFields.potential;
2843 ArrayBase& residualArray = (*_currentPotentialResidual)[potentialField];
2844 T *arrayData = (T*)(residualArray.
getData());
2845 const T residual = arrayData[0];
2851 const Field& thermalField = _batteryModelFields.temperature;
2852 ArrayBase& residualArray = (*_currentThermalResidual)[thermalField];
2853 T *arrayData = (T*)(residualArray.
getData());
2854 const T residual = arrayData[0];
2860 const Field& potentialSpeciesTempField = _batteryModelFields.potentialSpeciesTemp;
2861 ArrayBase& residualArray = (*_currentPCResidual)[potentialSpeciesTempField];
2862 T *arrayData = (T*)(residualArray.
getData());
2865 const T residual = arrayData[v];
2868 else if ((v==2)&&(_options.thermalModelPC))
2870 const T residual = arrayData[v];
2875 const T residual = 0.0;
2882 const int numMeshes =
_meshes.size();
2883 for (
int n=0; n<numMeshes; n++)
2909 for (
int f=0; f<faces.
getCount(); f++)
2911 int c0p = parentFaceCells(f,0);
2912 int c1p = parentFaceCells(f,1);
2920 int c0o = otherFaceCells(f,0);
2921 int c1o = otherFaceCells(f,1);
2930 const int c1 = cellCells(f,0);
2931 const int c2 = cellCells(f,1);
2932 const int c3 = cellCells(f,2);
2936 cout << speciesCell[c0] <<
" " << speciesCell[c1] <<
" " << speciesCell[c2] <<
" " << speciesCell[c3] << endl;
2940 speciesCell[c3] = speciesCellParent[c0p];
2941 speciesCell[c2] = speciesCellOther[c0o];
2945 cout << speciesCell[c0] <<
" " << speciesCell[c1] <<
" " << speciesCell[c2] <<
" " << speciesCell[c3] << endl;
2954 const int numMeshes =
_meshes.size();
2955 for (
int n=0; n<numMeshes; n++)
2962 const TArray& pSeparate =
dynamic_cast<const TArray&
>(_batteryModelFields.potential[cells]);
2963 const TArray& tSeparate =
dynamic_cast<const TArray&
>(_batteryModelFields.temperature[cells]);
2965 if (_options.thermalModelPC)
2968 for (
int c=0; c<cells.
getCount(); c++)
2970 T concentration = mFSeparate[c];
2971 T potential = pSeparate[c];
2972 T temperature = tSeparate[c];
2973 VectorT3& coupledCellVector = coupledValues[c];
2976 coupledCellVector[0] = potential;
2977 coupledCellVector[1] = concentration;
2978 coupledCellVector[2] = temperature;
2984 for (
int c=0; c<cells.
getCount(); c++)
2986 T concentration = mFSeparate[c];
2987 T potential = pSeparate[c];
2988 VectorT2& coupledCellVector = coupledValues[c];
2991 coupledCellVector[0] = potential;
2992 coupledCellVector[1] = concentration;
3002 const TArray& pFluxSeparate =
dynamic_cast<const TArray&
>(_batteryModelFields.potential_flux[faces]);
3003 const TArray& tFluxSeparate =
dynamic_cast<const TArray&
>(_batteryModelFields.heatFlux[faces]);
3004 if (_options.thermalModelPC)
3007 for (
int f=0; f<faces.
getCount(); f++)
3009 T concentrationFlux = mFFluxSeparate[f];
3010 T potentialFlux = pFluxSeparate[f];
3011 T heatFlux = tFluxSeparate[f];
3012 VectorT3& coupledCellFluxVector = coupledFluxValues[f];
3015 coupledCellFluxVector[0] = potentialFlux;
3016 coupledCellFluxVector[1] = concentrationFlux;
3017 coupledCellFluxVector[2] = heatFlux;
3023 for (
int f=0; f<faces.
getCount(); f++)
3025 T concentrationFlux = mFFluxSeparate[f];
3026 T potentialFlux = pFluxSeparate[f];
3027 VectorT2& coupledCellFluxVector = coupledFluxValues[f];
3030 coupledCellFluxVector[0] = potentialFlux;
3031 coupledCellFluxVector[1] = concentrationFlux;
3040 const TArray& pFluxSeparate =
dynamic_cast<const TArray&
>(_batteryModelFields.potential_flux[faces]);
3041 const TArray& tFluxSeparate =
dynamic_cast<const TArray&
>(_batteryModelFields.heatFlux[faces]);
3042 if (_options.thermalModelPC)
3045 for (
int f=0; f<faces.
getCount(); f++)
3047 T concentrationFlux = mFFluxSeparate[f];
3048 T potentialFlux = pFluxSeparate[f];
3049 T heatFlux = tFluxSeparate[f];
3050 VectorT3& coupledCellFluxVector = coupledFluxValues[f];
3053 coupledCellFluxVector[0] = potentialFlux;
3054 coupledCellFluxVector[1] = concentrationFlux;
3055 coupledCellFluxVector[2] = heatFlux;
3061 for (
int f=0; f<faces.
getCount(); f++)
3063 T concentrationFlux = mFFluxSeparate[f];
3064 T potentialFlux = pFluxSeparate[f];
3065 VectorT2& coupledCellFluxVector = coupledFluxValues[f];
3068 coupledCellFluxVector[0] = potentialFlux;
3069 coupledCellFluxVector[1] = concentrationFlux;
3075 if (_options.transient)
3077 const TArray& potSeparateN1 =
dynamic_cast<const TArray&
>(_batteryModelFields.potentialN1[cells]);
3079 const TArray& tSeparateN1 =
dynamic_cast<const TArray&
>(_batteryModelFields.temperatureN1[cells]);
3080 if (_options.thermalModelPC)
3084 for (
int c=0; c<cells.
getCount(); c++)
3086 const T potentialN1 = potSeparateN1[c];
3087 const T concentrationN1 = mFSeparateN1[c];
3088 const T temperatureN1 = tSeparateN1[c];
3089 VectorT3& coupledCellVectorN1 = coupledValuesN1[c];
3092 coupledCellVectorN1[1] = concentrationN1;
3093 coupledCellVectorN1[0] = potentialN1;
3094 coupledCellVectorN1[2] = temperatureN1;
3097 if (_options.timeDiscretizationOrder > 1)
3101 const TArray& tSeparateN2 =
dynamic_cast<const TArray&
>(_batteryModelFields.temperatureN2[cells]);
3102 for (
int c=0; c<cells.
getCount(); c++)
3104 const T concentrationN2 = mFSeparateN2[c];
3105 const T temperatureN2 = tSeparateN2[c];
3106 VectorT3& coupledCellVectorN2 = coupledValuesN2[c];
3109 coupledCellVectorN2[1] = concentrationN2;
3110 coupledCellVectorN2[2] = temperatureN2;
3118 for (
int c=0; c<cells.
getCount(); c++)
3120 const T potentialN1 = potSeparateN1[c];
3121 const T concentrationN1 = mFSeparateN1[c];
3122 VectorT2& coupledCellVectorN1 = coupledValuesN1[c];
3125 coupledCellVectorN1[1] = concentrationN1;
3126 coupledCellVectorN1[0] = potentialN1;
3129 if (_options.timeDiscretizationOrder > 1)
3133 for (
int c=0; c<cells.
getCount(); c++)
3135 const T concentrationN2 = mFSeparateN2[c];
3136 VectorT2& coupledCellVectorN2 = coupledValuesN2[c];
3139 coupledCellVectorN2[1] = concentrationN2;
3149 const int numMeshes =
_meshes.size();
3150 for (
int n=0; n<numMeshes; n++)
3158 TArray& pSeparate =
dynamic_cast<TArray&
>(_batteryModelFields.potential[cells]);
3159 TArray& tSeparate =
dynamic_cast<TArray&
>(_batteryModelFields.temperature[cells]);
3160 if (_options.thermalModelPC)
3163 for (
int c=0; c<cells.
getCount(); c++)
3165 VectorT3 coupledCellVector = coupledValues[c];
3166 T potential = coupledCellVector[0];
3167 T concentration = coupledCellVector[1];
3168 T temperature = coupledCellVector[2];
3171 pSeparate[c] = potential;
3172 mFSeparate[c] = concentration;
3173 tSeparate[c] = temperature;
3179 for (
int c=0; c<cells.
getCount(); c++)
3181 VectorT2 coupledCellVector = coupledValues[c];
3182 T potential = coupledCellVector[0];
3183 T concentration = coupledCellVector[1];
3186 pSeparate[c] = potential;
3187 mFSeparate[c] = concentration;
3196 TArray& pFluxSeparate =
dynamic_cast<TArray&
>(_batteryModelFields.potential_flux[faces]);
3197 TArray& tFluxSeparate =
dynamic_cast<TArray&
>(_batteryModelFields.heatFlux[faces]);
3198 if (_options.thermalModelPC)
3200 const VectorT3Array& coupledFluxValues =
dynamic_cast<const VectorT3Array&
>(_batteryModelFields.potentialSpeciesTempFlux[faces]);
3201 for (
int f=0; f<faces.
getCount(); f++)
3203 VectorT3 coupledCellFluxVector = coupledFluxValues[f];
3204 T potentialFlux = coupledCellFluxVector[0];
3205 T concentrationFlux = coupledCellFluxVector[1];
3206 T heatFlux = coupledCellFluxVector[2];
3209 pFluxSeparate[f] = potentialFlux;
3210 mFFluxSeparate[f] = concentrationFlux;
3211 tFluxSeparate[f] = heatFlux;
3216 const VectorT2Array& coupledFluxValues =
dynamic_cast<const VectorT2Array&
>(_batteryModelFields.potentialSpeciesTempFlux[faces]);
3217 for (
int f=0; f<faces.
getCount(); f++)
3219 VectorT2 coupledCellFluxVector = coupledFluxValues[f];
3220 T potentialFlux = coupledCellFluxVector[0];
3221 T concentrationFlux = coupledCellFluxVector[1];
3224 pFluxSeparate[f] = potentialFlux;
3225 mFFluxSeparate[f] = concentrationFlux;
3234 TArray& pFluxSeparate =
dynamic_cast<TArray&
>(_batteryModelFields.potential_flux[faces]);
3235 TArray& tFluxSeparate =
dynamic_cast<TArray&
>(_batteryModelFields.heatFlux[faces]);
3236 if (_options.thermalModelPC)
3238 const VectorT3Array& coupledFluxValues =
dynamic_cast<const VectorT3Array&
>(_batteryModelFields.potentialSpeciesTempFlux[faces]);
3239 for (
int f=0; f<faces.
getCount(); f++)
3241 VectorT3 coupledCellFluxVector = coupledFluxValues[f];
3242 T potentialFlux = coupledCellFluxVector[0];
3243 T concentrationFlux = coupledCellFluxVector[1];
3244 T heatFlux = coupledCellFluxVector[2];
3247 pFluxSeparate[f] = potentialFlux;
3248 mFFluxSeparate[f] = concentrationFlux;
3249 tFluxSeparate[f] = heatFlux;
3255 const VectorT2Array& coupledFluxValues =
dynamic_cast<const VectorT2Array&
>(_batteryModelFields.potentialSpeciesTempFlux[faces]);
3256 for (
int f=0; f<faces.
getCount(); f++)
3258 VectorT2 coupledCellFluxVector = coupledFluxValues[f];
3259 T potentialFlux = coupledCellFluxVector[0];
3260 T concentrationFlux = coupledCellFluxVector[1];
3263 pFluxSeparate[f] = potentialFlux;
3264 mFFluxSeparate[f] = concentrationFlux;
3270 if (_options.transient)
3272 TArray& potSeparateN1 =
dynamic_cast<TArray&
>(_batteryModelFields.potentialN1[cells]);
3274 TArray& tSeparateN1 =
dynamic_cast<TArray&
>(_batteryModelFields.temperatureN1[cells]);
3276 if (_options.thermalModelPC)
3278 const VectorT3Array& coupledValuesN1 =
dynamic_cast< const VectorT3Array&
>(_batteryModelFields.potentialSpeciesTempN1[cells]);
3280 for (
int c=0; c<cells.
getCount(); c++)
3282 const VectorT3& coupledCellVectorN1 = coupledValuesN1[c];
3285 mFSeparateN1[c] = coupledCellVectorN1[1];
3286 potSeparateN1[c] = coupledCellVectorN1[0];
3287 tSeparateN1[c] = coupledCellVectorN1[2];
3290 if (_options.timeDiscretizationOrder > 1)
3292 const VectorT3Array& coupledValuesN2 =
dynamic_cast<const VectorT3Array&
>(_batteryModelFields.potentialSpeciesTempN2[cells]);
3294 TArray& tSeparateN2 =
dynamic_cast<TArray&
>(_batteryModelFields.temperatureN2[cells]);
3295 for (
int c=0; c<cells.
getCount(); c++)
3297 const VectorT3& coupledCellVectorN2 = coupledValuesN2[c];
3300 mFSeparateN2[c] = coupledCellVectorN2[1];
3301 tSeparateN2[c] = coupledCellVectorN2[2];
3307 const VectorT2Array& coupledValuesN1 =
dynamic_cast< const VectorT2Array&
>(_batteryModelFields.potentialSpeciesTempN1[cells]);
3309 for (
int c=0; c<cells.
getCount(); c++)
3311 const VectorT2& coupledCellVectorN1 = coupledValuesN1[c];
3314 mFSeparateN1[c] = coupledCellVectorN1[1];
3315 potSeparateN1[c] = coupledCellVectorN1[0];
3318 if (_options.timeDiscretizationOrder > 1)
3320 const VectorT2Array& coupledValuesN2 =
dynamic_cast<const VectorT2Array&
>(_batteryModelFields.potentialSpeciesTempN2[cells]);
3322 for (
int c=0; c<cells.
getCount(); c++)
3324 const VectorT2& coupledCellVectorN2 = coupledValuesN2[c];
3327 mFSeparateN2[c] = coupledCellVectorN2[1];
3337 const int numMeshes =
_meshes.size();
3338 for (
int n=0; n<numMeshes; n++)
3345 const TArray& pDiffSeparate =
dynamic_cast<const TArray&
>(_batteryModelFields.conductivity[cells]);
3346 const TArray& tDiffSeparate =
dynamic_cast<const TArray&
>(_batteryModelFields.thermalConductivity[cells]);
3348 if (_options.thermalModelPC)
3352 for (
int c=0; c<cells.
getCount(); c++)
3354 T massDiff = mFDiffSeparate[c];
3355 T potentialDiff = pDiffSeparate[c];
3356 T thermalDiff = tDiffSeparate[c];
3357 VectorT3& coupledCellDiffVector = coupledDiffValues[c];
3360 coupledCellDiffVector[0] = potentialDiff;
3361 coupledCellDiffVector[1] = massDiff;
3362 coupledCellDiffVector[2] = thermalDiff;
3369 for (
int c=0; c<cells.
getCount(); c++)
3371 T massDiff = mFDiffSeparate[c];
3372 T potentialDiff = pDiffSeparate[c];
3373 VectorT2& coupledCellDiffVector = coupledDiffValues[c];
3376 coupledCellDiffVector[0] = potentialDiff;
3377 coupledCellDiffVector[1] = massDiff;
3391 const int nFaces = faces.
getCount();
3392 const TArray& faceAreaMag =
dynamic_cast<const TArray&
>(_geomFields.areaMag[faces]);
3394 for(
int f=0; f<nFaces; f++)
3396 totalArea += faceAreaMag[f];
3398 cout <<
"Percent Done: " << (f*100.0/nFaces) <<
"%" << endl;
3403 throw CException(
"getFaceGroupArea: No face group with given id");
3414 const int nFaces = faces.
getCount();
3415 const TArray& faceAreaMag =
dynamic_cast<const TArray&
>(_geomFields.areaMag[faces]);
3418 const TArray& cellPotential =
dynamic_cast<const TArray&
>(_batteryModelFields.potential[cells]);
3421 for(
int f=0; f<nFaces; f++)
3424 const T faceVoltage = cellPotential[faceCells(f,1)];
3425 totalArea += faceAreaMag[f];
3426 voltageSum += faceVoltage*faceAreaMag[f];
3428 return (voltageSum/totalArea);
3431 throw CException(
"getFaceGroupVoltage: No face group with given id");
3437 const TArray& cellVolume =
dynamic_cast<const TArray&
>(_geomFields.volume[cells]);
3438 T totalVolume = 0.0;
3441 totalVolume += cellVolume[c];
3481 const int nSpecies) :
3483 _impl(new
Impl(geomFields,realMeshes,meshes,nSpecies))
3540 _impl->advanceSpecies(niter);
3547 _impl->advancePotential(niter);
3554 _impl->advanceThermal(niter);
3561 _impl->advanceCoupled(niter);
3568 _impl->updateTime();
3575 _impl->recoverLastTimestep();
3583 return _impl->getMassFluxIntegral(mesh, faceGroupId, m);
3590 return _impl->getPotentialFluxIntegral(mesh, faceGroupId);
3597 return _impl->getHeatFluxIntegral(mesh, faceGroupId);
3604 return _impl->getAverageConcentration(mesh, m);
3611 return _impl->getSpeciesResidual(speciesId);
3618 return _impl->getPotentialResidual();
3625 return _impl->getThermalResidual();
3632 return _impl->getPCResidual(v);
3639 _impl->copyCoupledToSeparate();
3646 _impl->copySeparateToCoupled();
3653 return _impl->getFaceGroupArea(mesh, fgID);
3660 return _impl->getFaceGroupVoltage(mesh, fgID);
3667 return _impl->getMeshVolume(mesh);
BatteryModelFields _batteryModelFields
vector< BatterySpeciesFields * > _speciesFieldsVector
vector< MFRPtr * > _currentSpeciesResidual
T getFaceGroupVoltage(const Mesh &mesh, const int fgID)
const FaceGroupList & getBoundaryFaceGroups() const
Array< Gradient< VectorT3 > > VectorT3GradArray
bool isDoubleShell() const
void advanceThermal(const int niter)
BatterySpeciesBCMap & getSpeciesBCMap(const int speciesId)
Matrix & getMatrix(const Index &rowIndex, const Index &colIndex)
shared_ptr< FaceGroup > FaceGroupPtr
BatteryModelFields & getBatteryModelFields()
BatterySpeciesBCMap & getSpeciesBCMap(const int speciesId)
BatteryPotentialVCMap & getPotentialVCMap()
BatteryThermalBCMap _tbcMap
void linearizeSpecies(LinearSystem &ls, LinearSystem &lsShell, const int &m)
BatteryModelOptions< T > & getOptions()
bool hasArray(const StorageSite &s) const
const StorageSite & getParentFaceGroupSite() const
BatteryPotentialBCMap & getPotentialBCMap()
T getMassFluxIntegral(const Mesh &mesh, const int faceGroupId, const int m)
void discretize(const Mesh &mesh, const Mesh &parentMesh, const Mesh &otherMesh, MultiFieldMatrix &mfmatrix, MultiField &xField, MultiField &rField)
vector< MFRPtr * > _initialSpeciesNormVector
void printMatrixElementsOnFace(const Mesh &mesh, const int fgId, LinearSystem &ls, Field &varField)
const FaceGroupList & getAllFaceGroups() const
void copySeparateToCoupled()
void initPotentialLinearization(LinearSystem &ls)
T getSpeciesResidual(const int speciesId)
Impl(GeomFields &geomFields, const MeshList &realMeshes, const MeshList &meshes, const int nSpecies)
bool isConnectedShell() const
OffDiag & getCoeff(const int i, const int j)
T getAverageConcentration(const Mesh &mesh, const int m)
MFRPtr _currentPotentialResidual
BatterySpeciesFields & getBatterySpeciesFields(const int speciesId)
BatterySpeciesVCMap & getSpeciesVCMap(const int speciesId)
void advanceCoupled(const int niter)
LinearSystem & matrixMerge(LinearSystem &ls, const int m)
const FaceGroup & getFaceGroup(const int fgId) const
T getPotentialFluxIntegral(const Mesh &mesh, const int faceGroupId)
BatteryModelFields & getBatteryModelFields()
BatteryThermalVCMap & getThermalVCMap()
Array< Diag > & getDiag()
DiagonalTensor< T, 3 > DiagTensorT3
void discretize(const Mesh &mesh, const Mesh &parentMesh, const Mesh &otherMesh, MultiFieldMatrix &mfmatrix, MultiField &xField, MultiField &rField)
Array< Gradient< T > > TGradArray
void advanceSpecies(const int niter)
T getPCResidual(const int v)
MFRPtr _currentThermalResidual
FloatVal< T > getVal(const string varName) const
Array< Vector< double, 3 > > VectorT3Array
int getOtherMeshID() const
void linearizeThermal(LinearSystem &ls)
Array< VectorT3 > VectorT3Array
T getFaceGroupVoltage(const Mesh &mesh, const int fgID)
const StorageSite & getOtherFaceGroupSite() const
void copySeparateToCoupled()
void advancePotential(const int niter)
SquareTensor< T, 2 > SquareTensorT2
T getPotentialFluxIntegral(const Mesh &mesh, const int faceGroupId)
std::map< int, BatterySpeciesVC< T > * > BatterySpeciesVCMap
BatteryModel(GeomFields &geomFields, const MeshList &realMeshes, const MeshList &meshes, const int nSpecies)
void initThermalLinearization(LinearSystem &ls)
T getMeshVolume(const Mesh &mesh)
T getAverageConcentration(const Mesh &mesh, const int m)
void discretize(const Mesh &mesh, const Mesh &parentMesh, const Mesh &otherMesh, MultiFieldMatrix &mfmatrix, MultiField &xField, MultiField &rField, LinearSystem &lsShell)
pair< const Field *, const StorageSite * > ArrayIndex
vector< BatterySpeciesBCMap * > _sbcMapVector
void advancePotential(const int niter)
Gradient< VectorT2 > VectorT2Grad
void linearizePC_Thermal(LinearSystem &ls)
T getSpeciesResidual(const int speciesId)
BatterySpeciesVCMap & getSpeciesVCMap(const int speciesId)
void recoverLastTimestep()
vector< shared_ptr< Discretization > > DiscrList
const StorageSite & getFaces() const
std::map< int, BatterySpeciesBC< T > * > BatterySpeciesBCMap
const MeshList _realMeshes
const CRConnectivity & getCellCells() const
const StorageSite & getCells() const
void applyInterfaceBC(const int f) const
void advanceSpecies(const int niter)
Gradient< VectorT3 > VectorT3Grad
BatteryThermalVCMap & getThermalVCMap()
T getHeatFluxIntegral(const Mesh &mesh, const int faceGroupId)
void addArray(const StorageSite &, shared_ptr< ArrayBase > a)
const CRConnectivity & getFaceCells(const StorageSite &site) const
Array< Gradient< VectorT2 > > VectorT2GradArray
void recoverLastTimestep()
int getParentMeshID() const
SquareTensor< T, 3 > SquareTensorT3
std::map< int, BatteryPotentialBC< T > * > BatteryPotentialBCMap
BatteryThermalBCMap & getThermalBCMap()
void addMatrix(const Index &rowI, const Index &colI, shared_ptr< Matrix > m)
BatteryPotentialVCMap & getPotentialVCMap()
DiagonalTensor< T, 2 > DiagTensorT2
T getPCResidual(const int v)
virtual void * getData() const =0
void initPCLinearization(LinearSystem &ls)
void advanceThermal(const int niter)
void copyCoupledToSeparate()
CRMatrix< T, T, T > T_Matrix
void linearizePC(LinearSystem &ls)
vector< BatterySpeciesVCMap * > _svcMapVector
BatteryPotentialVCMap _pvcMap
T getFaceGroupArea(const Mesh &mesh, const int fgID)
MFRPtr _initialPotentialNorm
void copyCoupledToSeparate()
shared_ptr< MultiFieldReduction > MFRPtr
MFRPtr _currentPCResidual
void addArray(const ArrayIndex &aIndex, shared_ptr< ArrayBase > a)
BatterySpeciesFields & getBatterySpeciesFields(const int speciesId)
T getMeshVolume(const Mesh &mesh)
const FaceGroupList & getInterfaceGroups() const
T getFaceGroupArea(const Mesh &mesh, const int fgID)
void discretize(const Mesh &mesh, const Mesh &parentMesh, const Mesh &otherMesh, MultiFieldMatrix &mfmatrix, MultiField &xField, MultiField &rField)
Array< VectorT2 > VectorT2Array
void discretize(const Mesh &mesh, const Mesh &parentMesh, const Mesh &otherMesh, MultiFieldMatrix &mfmatrix, MultiField &xField, MultiField &rField)
T getMassFluxIntegral(const Mesh &mesh, const int faceGroupId, const int m)
void linearizePotential(LinearSystem &ls)
std::map< int, BatteryPotentialVC< T > * > BatteryPotentialVCMap
std::map< int, BatteryThermalBC< T > * > BatteryThermalBCMap
shared_ptr< ArrayBase > getArrayPtr(const StorageSite &)
BatteryPotentialBCMap & getPotentialBCMap()
void initSpeciesLinearization(LinearSystem &ls, LinearSystem &lsShell, const int &SpeciesNumber)
void advanceCoupled(const int niter)
T getHeatFluxIntegral(const Mesh &mesh, const int faceGroupId)
BatteryThermalVCMap _tvcMap
virtual void linearize(DiscrList &discretizations, const MeshList &meshes, MultiFieldMatrix &matrix, MultiField &x, MultiField &b)
void discretize(const Mesh &mesh, const Mesh &parentMesh, const Mesh &otherMesh, MultiFieldMatrix &mfmatrix, MultiField &xField, MultiField &rField)
std::map< int, BatteryThermalVC< T > * > BatteryThermalVCMap
BatteryThermalBCMap & getThermalBCMap()
MultiFieldMatrix & getMatrix()
vector< Mesh * > MeshList
BatteryModelOptions< T > & getOptions()
BatteryPotentialBCMap _pbcMap
BatteryModelOptions< T > _options
MFRPtr _initialThermalNorm