Memosa-FVM  0.2
BatteryLinearizeSpeciesInterface< X, Diag, OffDiag > Class Template Reference

#include <BatteryLinearizeSpeciesInterface.h>

Collaboration diagram for BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >:

Public Types

typedef NumTypeTraits< X >
::T_Scalar 
T_Scalar
 
typedef CRMatrix< Diag,
OffDiag, X > 
CCMatrix
 
typedef CCMatrix::DiagArray DiagArray
 
typedef Array< T_ScalarTArray
 
typedef Array< X > XArray
 
typedef Vector< T_Scalar, 3 > VectorT3
 
typedef Array< VectorT3VectorT3Array
 

Public Member Functions

 BatteryLinearizeSpeciesInterface (const GeomFields &geomFields, const T_Scalar RRConstant, const T_Scalar interfaceUnderRelax, const bool Anode, const bool Cathode, Field &varField, Field &speciesConcElectricModel, Field &elecPotentialField, Field &temperatureField)
 
void discretize (const Mesh &mesh, const Mesh &parentMesh, const Mesh &otherMesh, MultiFieldMatrix &mfmatrix, MultiField &xField, MultiField &rField)
 

Private Attributes

const GeomFields_geomFields
 
Field_varField
 
Field_speciesConcElectricModel
 
Field_elecPotentialField
 
Field_temperatureField
 
const T_Scalar _RRConstant
 
const T_Scalar _interfaceUnderRelax
 
const bool _Anode
 
const bool _Cathode
 

Detailed Description

template<class X, class Diag, class OffDiag>
class BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >

Definition at line 24 of file BatteryLinearizeSpeciesInterface.h.

Member Typedef Documentation

template<class X, class Diag, class OffDiag>
typedef CRMatrix<Diag,OffDiag,X> BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::CCMatrix

Definition at line 28 of file BatteryLinearizeSpeciesInterface.h.

template<class X, class Diag, class OffDiag>
typedef CCMatrix::DiagArray BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::DiagArray

Definition at line 29 of file BatteryLinearizeSpeciesInterface.h.

template<class X, class Diag, class OffDiag>
typedef NumTypeTraits<X>::T_Scalar BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::T_Scalar

Definition at line 27 of file BatteryLinearizeSpeciesInterface.h.

template<class X, class Diag, class OffDiag>
typedef Array<T_Scalar> BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::TArray

Definition at line 30 of file BatteryLinearizeSpeciesInterface.h.

template<class X, class Diag, class OffDiag>
typedef Vector<T_Scalar,3> BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::VectorT3

Definition at line 32 of file BatteryLinearizeSpeciesInterface.h.

template<class X, class Diag, class OffDiag>
typedef Array<VectorT3> BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::VectorT3Array

Definition at line 33 of file BatteryLinearizeSpeciesInterface.h.

template<class X, class Diag, class OffDiag>
typedef Array<X> BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::XArray

Definition at line 31 of file BatteryLinearizeSpeciesInterface.h.

Constructor & Destructor Documentation

template<class X, class Diag, class OffDiag>
BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::BatteryLinearizeSpeciesInterface ( const GeomFields geomFields,
const T_Scalar  RRConstant,
const T_Scalar  interfaceUnderRelax,
const bool  Anode,
const bool  Cathode,
Field varField,
Field speciesConcElectricModel,
Field elecPotentialField,
Field temperatureField 
)
inline

Definition at line 36 of file BatteryLinearizeSpeciesInterface.h.

Member Function Documentation

template<class X, class Diag, class OffDiag>
void BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::discretize ( const Mesh mesh,
const Mesh parentMesh,
const Mesh otherMesh,
MultiFieldMatrix mfmatrix,
MultiField xField,
MultiField rField 
)
inline

Definition at line 57 of file BatteryLinearizeSpeciesInterface.h.

References BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_Anode, BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_Cathode, BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_elecPotentialField, BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_geomFields, BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_interfaceUnderRelax, BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_RRConstant, BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_speciesConcElectricModel, BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_temperatureField, BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_varField, GeomFields::areaMag, Mesh::getCellCells(), Mesh::getCells(), CRMatrix< T_Diag, T_OffDiag, X >::getCoeff(), StorageSite::getCount(), CRMatrix< T_Diag, T_OffDiag, X >::getDiag(), Mesh::getFaceCells(), MultiFieldMatrix::getMatrix(), Mesh::getOtherFaceGroupSite(), Mesh::getParentFaceGroupSite(), and StorageSite::getSelfCount().

Referenced by BatteryModel< T >::Impl::linearizeSpecies().

60  {
61  const StorageSite& cells = mesh.getCells();
62  const StorageSite& faces = mesh.getParentFaceGroupSite();
63 
64  // previous timestep shell mesh info
65  const XArray& speciesConcElecModel =
66  dynamic_cast<const XArray&>(_speciesConcElectricModel[cells]);
67 
68  // shell mesh info
69  const MultiField::ArrayIndex cVarIndex(&_varField,&cells);
70  CCMatrix& matrix = dynamic_cast<CCMatrix&>(mfmatrix.getMatrix(cVarIndex,cVarIndex));
71  const XArray& xCell = dynamic_cast<const XArray&>(xField[cVarIndex]);
72  const CRConnectivity& cellCells = mesh.getCellCells();
73  XArray& rCell = dynamic_cast<XArray&>(rField[cVarIndex]);
74  DiagArray& diag = matrix.getDiag();
75 
76  // shell mesh electrical potential values
77  const XArray& ePotCell =
78  dynamic_cast<const XArray&>(_elecPotentialField[cells]);
79 
80  // shell mesh temperature values
81  const XArray& eTempCell =
82  dynamic_cast<const XArray&>(_temperatureField[cells]);
83 
84 
85 
86  // In the following, parent is assumed to be the electrolyte, and
87  // the other mesh is assumed to be electrode when implimenting
88  // the Butler-Volmer equations
89 
90  // parent mesh info
91  const CRConnectivity& parentFaceCells = parentMesh.getFaceCells(faces);
92  const StorageSite& parentCells = parentMesh.getCells();
93  const MultiField::ArrayIndex cVarIndexParent(&_varField,&parentCells);
94  XArray& rParentCell = dynamic_cast<XArray&>(rField[cVarIndexParent]);
95  CCMatrix& parentmatrix = dynamic_cast<CCMatrix&>(mfmatrix.getMatrix(cVarIndexParent,cVarIndexParent));
96  DiagArray& parentdiag = parentmatrix.getDiag();
97  const TArray& faceAreaMag =
98  dynamic_cast<const TArray&>(_geomFields.areaMag[faces]);
99 
100  // other mesh info
101  const StorageSite& otherFaces = mesh.getOtherFaceGroupSite();
102  const CRConnectivity& otherFaceCells = otherMesh.getFaceCells(otherFaces);
103  const StorageSite& otherCells = otherMesh.getCells();
104  const MultiField::ArrayIndex cVarIndexOther(&_varField,&otherCells);
105  XArray& rOtherCell = dynamic_cast<XArray&>(rField[cVarIndexOther]);
106  CCMatrix& othermatrix = dynamic_cast<CCMatrix&>(mfmatrix.getMatrix(cVarIndexOther,cVarIndexOther));
107  DiagArray& otherdiag = othermatrix.getDiag();
108 
109  // set constants for entire shell
110  const T_Scalar F = 96485.0; // C/mol
111  const T_Scalar k = _RRConstant;
112  T_Scalar csMax = 26000.0;
113  if (_Anode){
114  csMax = 26390.0;}
115  if (_Cathode){
116  csMax = 22860.0;}
117  const T_Scalar alpha_a = 0.5;
118  const T_Scalar alpha_c = 0.5;
119  const T_Scalar R = 8.314; // J/mol/K
120  const T_Scalar dU_dT = -0.0011; // V/K
121 
122  for (int f=0; f<faces.getCount(); f++)
123  {
124  //get parent mesh fluxes and coeffs
125  int c0p = parentFaceCells(f,0);
126  int c1p = parentFaceCells(f,1);
127  if (c1p < parentCells.getSelfCount())
128  {
129  // c0 is ghost cell and c1 is boundry cell, so swap cell numbers
130  // so that c1p refers to the ghost cell in the following
131  int temp = c0p;
132  c0p = c1p;
133  c1p = temp;
134  }
135 
136  const X parentFlux = rParentCell[c1p]; // inward shell flux on the left
137  const OffDiag dRC0dXC3 = parentmatrix.getCoeff(c1p, c0p);
138  const Diag dRC0dXC0 = parentdiag[c1p];
139 
140  //get other mesh fluxes and coeffs
141  int c0o = otherFaceCells(f,0);
142  int c1o = otherFaceCells(f,1);
143  if (c1o < otherCells.getSelfCount())
144  {
145  // c0 is ghost cell and c1 is boundry cell, so swap cell numbers
146  // so that c1o refers to the ghost cell in the following
147  int temp = c0o;
148  c0o = c1o;
149  c1o = temp;
150  }
151 
152  const X otherFlux = rOtherCell[c1o]; // inward shell flux on the right
153  const OffDiag dRC0dXC2 = othermatrix.getCoeff(c1o, c0o);
154  const OffDiag dRC0dXC1 = otherdiag[c1o];
155 
156 
157  //now put flux information from meshes into shell cells
158  const int c0 = f;
159  const int c1 = cellCells(f,0);
160  const int c2 = cellCells(f,1);
161  const int c3 = cellCells(f,2);
162 
163  const T_Scalar Temp = eTempCell[c0]; // K, c0 and c1 should be same Temp at convergence
164  const T_Scalar C_a = alpha_a*F/R/Temp;
165  const T_Scalar C_c = alpha_c*F/R/Temp;
166  const T_Scalar Area = faceAreaMag[c0];
167 
168  T_Scalar cs_star = xCell[c1];
169  T_Scalar ce_star = xCell[c0];
170 
171  // avoid nans
172  if (cs_star < 0.0){ cout << "ERROR: Cs < 0, Cs=" << cs_star << endl; cs_star = 0.0;}
173  if (ce_star < 0.0){ cout << "ERROR: Ce < 0, Ce=" << ce_star << endl; ce_star = 0.0;}
174  if (cs_star > csMax){ cout << "ERROR: Cs > CsMax, Cs=" << cs_star << endl; cs_star = csMax;}
175 
176  const T_Scalar SOC = speciesConcElecModel[c1]/csMax;
177 
178  T_Scalar U_ref = 0.1; // V
179  if (_Anode){
180  U_ref = -0.16 + 1.32*exp(-3.0*SOC)+10.0*exp(-2000.0*SOC);
181  if (U_ref < 0.0)
182  {U_ref = 0.0; cout << "U_ref < 0" << endl;}
183  if (U_ref > 1.2)
184  {U_ref = 1.2; cout << "U_ref > 1.2" << endl;}
185  }
186  if (_Cathode){
187  U_ref = 4.19829 + 0.0565661*tanh(-14.5546*SOC + 8.60942) - 0.0275479*(1.0/pow((0.998432-SOC),0.492465) - 1.90111) - 0.157123*exp(-0.04738*pow(SOC,8.0)) + 0.810239*exp(-40.0*(SOC-0.133875));
188  if (U_ref < 0.0)
189  {U_ref = 0.0; cout << "U_ref < 0" << endl;}
190  if (U_ref > 5.0)
191  {U_ref = 5.0; cout << "U_ref > 5.0" << endl;}
192  }
193 
194  const T_Scalar U = U_ref - (Temp - 298.0)*dU_dT;
195  const T_Scalar eta_star = ePotCell[c1] - ePotCell[c0] - U;
196 
197  //const T_Scalar eta_star = _A_coeff - _B_coeff - U_ref;
198  T_Scalar C_0 = exp(C_a*eta_star)-exp(-1.0*C_c*eta_star);
199 
200  const T_Scalar i_star = C_0*k*F*Area*pow(ce_star,alpha_c)*pow((csMax-cs_star),alpha_a)*pow(cs_star,alpha_c);
201 
202  // CURRENT SHOULD NOT BE ZERO
203  //if (i_star == 0.0){cout << "WARNING: current = 0" << endl;}
204 
205  // calculate dC_0/dCS
206  T_Scalar dC_0dCS = 0.0;
207  const T_Scalar dC0dEta = (C_a*exp(C_a*eta_star) + C_c*exp(-1*C_c*eta_star));
208  if (_Anode)
209  {
210  dC_0dCS = dC0dEta*(-1.0)*(-20000.0*exp(-2000.0*SOC) - 3.96*exp(-3.0*SOC))*(1.0/csMax);
211  }
212  if (_Cathode)
213  {
214  dC_0dCS = dC0dEta*(-1.0)*(-0.0135664/pow((0.998432-SOC),1.49247) - 0.823297/pow(cosh(8.60942-14.5546*SOC),2.0) + 0.0595559*exp(-0.04738*pow(SOC,8.0))*pow(SOC,7.0) - 6859.94*exp(-40.0*SOC))*(1.0/csMax);
215  }
216 
217  const T_Scalar dIdCS_star = i_star*(alpha_c/cs_star - alpha_a/(csMax-cs_star)+ dC_0dCS/C_0);
218 
219  const T_Scalar dIdCE_star = i_star*alpha_c/ce_star;
220 
221  // left(parent) shell cell - 3 neighbors
222  // flux balance
223  OffDiag& offdiagC0_C1 = matrix.getCoeff(c0, c1);
224  OffDiag& offdiagC0_C2 = matrix.getCoeff(c0, c2);
225  OffDiag& offdiagC0_C3 = matrix.getCoeff(c0, c3);
226 
227  rCell[c0] = F*otherFlux + F*parentFlux;
228  offdiagC0_C1 = F*dRC0dXC1;
229  offdiagC0_C3 = F*dRC0dXC3;
230  offdiagC0_C2 = F*dRC0dXC2;
231  diag[c0] = F*dRC0dXC0;
232 
233  // right(other) shell cell - 2 neighbors
234  // jump condition
235  OffDiag& offdiagC1_C0 = matrix.getCoeff(c1, c0);
236  OffDiag& offdiagC1_C2 = matrix.getCoeff(c1, c2);
237 
238  rCell[c1] = otherFlux*F - (i_star + dIdCS_star*(xCell[c1]-cs_star) + dIdCE_star*(xCell[c0]-ce_star));
239  offdiagC1_C0 = -1*dIdCE_star;
240  offdiagC1_C2 = F*dRC0dXC2;
241  //make sure diag is < 0
242  if (dIdCS_star > 0.0)
243  {
244  diag[c1] = F*dRC0dXC1 - dIdCS_star;
245  }
246  else
247  {
248  diag[c1] = F*dRC0dXC1;
249  }
250 
251  // set other coeffs to zero for right shell cell
252  OffDiag& offdiagC1_C3 = matrix.getCoeff(c1, c3);
253  offdiagC1_C3 = 0.0;
254 
255  // underrelax diagonal to help convergence
256  diag[c1] = 1/_interfaceUnderRelax*diag[c1];
257 
258  // some output of prevailing or starred values - useful for testing
259 
260  /*if (c0 == 0){
261  cout << "C_0: " << C_0 << endl;
262  cout << "C_s: " << cs_star << " C_e: " << ce_star << " i: " << i_star << " dIdCs: " << dIdCS_star << " dIdCe: " << dIdCE_star << endl;
263  cout <<"Diag: " << diag[c1] << " dRdXc2: " << offdiagC1_C2 << " dRdXc0: " << offdiagC1_C0 << endl;
264  cout << " " << endl;
265  }*/
266 
267  if (c0 == 0){
268  if (_Cathode)
269  {
270  //cout << "UrefAnode: " << U_ref << endl;
271  //cout << "Cs0: " << cs_star << endl;
272  }
273  }
274 
275  }
276 
277  }
Matrix & getMatrix(const Index &rowIndex, const Index &colIndex)
int getSelfCount() const
Definition: StorageSite.h:40
const StorageSite & getParentFaceGroupSite() const
Definition: Mesh.h:329
const StorageSite & getOtherFaceGroupSite() const
Definition: Mesh.h:332
pair< const Field *, const StorageSite * > ArrayIndex
Definition: MultiField.h:21
const CRConnectivity & getCellCells() const
Definition: Mesh.cpp:480
const StorageSite & getCells() const
Definition: Mesh.h:109
const CRConnectivity & getFaceCells(const StorageSite &site) const
Definition: Mesh.cpp:388
int getCount() const
Definition: StorageSite.h:39
Field areaMag
Definition: GeomFields.h:25

Member Data Documentation

template<class X, class Diag, class OffDiag>
const bool BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_Anode
private
template<class X, class Diag, class OffDiag>
const bool BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_Cathode
private
template<class X, class Diag, class OffDiag>
Field& BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_elecPotentialField
private
template<class X, class Diag, class OffDiag>
const GeomFields& BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_geomFields
private
template<class X, class Diag, class OffDiag>
const T_Scalar BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_interfaceUnderRelax
private
template<class X, class Diag, class OffDiag>
const T_Scalar BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_RRConstant
private
template<class X, class Diag, class OffDiag>
Field& BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_speciesConcElectricModel
private
template<class X, class Diag, class OffDiag>
Field& BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_temperatureField
private
template<class X, class Diag, class OffDiag>
Field& BatteryLinearizeSpeciesInterface< X, Diag, OffDiag >::_varField
private

The documentation for this class was generated from the following file: