2.7. Battery Model DEFINE Macros

This section contains descriptions of DEFINE macros for the MSMD-based battery model. The functions can be hooked up from the Battery Model dialog box (UDF tab). Table 2.14: Quick Reference Guide for Battery Model-Specific DEFINE Macros provides a quick reference guide to the battery model DEFINE macros, the functions they define, and the dialog boxes where they are activated in Ansys Fluent. For your convenience, they are listed in Battery Model DEFINE Macros. Definitions of each DEFINE macro are contained in the udf.h header file.


Note:  All the battery model UDFs can only be compiled and cannot be run in the interpreted mode.


Table 2.14: Quick Reference Guide for Battery Model-Specific DEFINE Macros

Function

DEFINE Macro

Dialog Box Activated In

abuse reaction rate for the 1-eq abuse reaction modelDEFINE_BATTERY_ABUSE_RATE Battery Model
cell clustering target variable DEFINE_BATTERY_CLUSTER Battery Model
voltage-current relationship for the user-defined electrochemical model DEFINE_BATTERY_ECHEM_MODEL Battery Model
electric load type and value DEIFNE_BATTERY_ELOAD_PROFILE Battery Model
entropic heat term DEFINE_BATTERY_ENTROPIC_HEAT Battery Model
the Butler-Volmer rate for the Newman's P2D model DEFINE_BATTERY_NEWMAN_BV_RATE Battery Model
export the Newman's P2D model results DEFINE_BATTERY_NEWMAN_POSTPROCESSING Battery Model
parameters for the ECM model DEFINE_BATTERY_PARAMETER_ECM Battery Model
U and Y functions for the NTGK model DEFINE_BATTERY_PARAMETER_NTGK Battery Model
material properties for the Newman's P2D model DEFINE_BATTERY_PROPERTY Battery Model
normal vector of the battery electrode layer for the battery swelling model DEFINE_BATTERY_SWELL_LAYER_N Battery Model
swelling strain for the NTGK or ECM model DEFINE_BATTERY_SWELL_STRAIN Battery Model

2.7.1. DEFINE_BATTERY_ABUSE_RATE

2.7.1.1. Description

You can use DEIFNE_BATTERY_ABUSE_RATE to specify the abuse rate in the one-equation thermal abuse model.

2.7.1.2. Usage

DEIFNE_BATTERY_ABUSE_RATE (name, T, alpha)

Argument Type

Description

symbol name

UDF name.

real T

Temperature.

real alpha

Reaction progress variable.

Function returns

real

There are three arguments to DEIFNE_BATTERY_ABUSE_RATE: name, T, and alpha. You supply name, the name of the UDF. T and alpha are variables that are passed by the Ansys Fluent solver to your UDF. Your function will return a value of the abuse rate.

2.7.1.3. Example

The example shows the usage of DEFINE_BATTERY_ABUSE_RATE. The UDF implements the default Arrhenius rate in Ansys Fluent (see Equation 19–33 in the Fluent Theory Guide).

#include "udf.h"

DEFINE_BATTERY_ABUSE_RATE(abuse_rate, T, alpha)
{
  real A =8.3e14 ,  E =1.54e5 , m = 0.0,  n =1.0, R =8.314  ; 
  real value;

  value = A*exp(E/(R*T))*pow(alpha, m) * pow((1.0-alpha), n);

  return value;
}

2.7.1.4. Hooking a DEFINE_BATTERY_ABUSE_RATE UDF to Ansys Fluent

After the UDF that you have defined using DEFINE_BATTERY_ABUSE_RATE is compiled (Compiling UDFs), the name of the argument that you supplied as the first DEFINE macro argument will become visible and selectable in the Battery Model dialog box (Advanced Options tab). See Hooking Battery Model UDFs for details.

2.7.2. DEFINE_BATTERY_CLUSTER

2.7.2.1. Description

You can use DEFINE_BATTERY_CLUSTER to specify the target variable in cell clustering.

2.7.2.2. Usage

DEFINE_BATTERY_CLUSTER (name, c, t)

Argument Type

Description

symbol name

UDF name.

cell_t c

Cell index.

Thread *t

Pointer to the cell thread.

Function returns

real

There are three arguments to DEFINE_BATTERY_CLUSTER: name, c, and t. You supply name, the name of the UDF. c and t are variables that are passed by the Ansys Fluent solver to your UDF. Your function will return a value of the cell clustering variable.

2.7.2.3. Example

The example shows the usage of DEFINE_BATTERY_CLUSTER. In a jelly roll battery simulation, radius could be used as the target variable. The following code shows an example of such a UDF.

#include "udf.h"

DEFINE_BATTERY_CLUSTER(battery_clustering, c, t)
{
   real value, x[3];

  C_CENTROID(x, c, t);
  value = sqrt(x[0]*x[0] + x[1]*x[1]);  /* use radius as the clustering criterion */

  return value;
}

2.7.2.4. Hooking a DEFINE_BATTERY_CLUSTER UDF to Ansys Fluent

After the UDF that you have defined using DEFINE_BATTERY_CLUSTER is compiled (Compiling UDFs), the name of the argument that you supplied as the first DEFINE macro argument will become visible and selectable in the Battery Model dialog box (Model Options tab). See Hooking Battery Model UDFs for details.

2.7.3. DEFINE_BATTERY_ECHEM_MODEL

2.7.3.1. Description

You can use DEFINE_BATTERY_ECHEM_MODEL to specify the voltage-current relationship used in the user-defined electrochemical model. You need to define both scenarios:

  • computing voltage when current is specified

  • computing current when voltage is specified

2.7.3.2. Usage

DEFINE_BATTERY_ECHEM_MODEL (name, zero_start, mode, temperature, voltage_in, current_in, dt, current_out, Qe, voltage_out)

Argument Type

Description

symbol name

UDF name.

int zero_start

Flag to indicate whether or not the submodel is to be initialized. A value of 0 indicates the initial UDF call requesting submodel initialization. A value of 1 indicates the subsequent call.

int mode

Flag indicating which electric load boundary type is used:

  • mode = 0 indicates that the voltage load is used. voltage_in is the input, and current_out needs to be computed

  • mode = 1 indicates that the current load is used. current_in is the input, and voltage_out needs to be computed.

real temperature

Temperature at the time the submodel is called.

real voltage_in

A voltage value. This value is used as an input when the voltage load boundary condition is used.

real current_in

A current value. This value is used as an input when the current load boundary condition is used.

real dt

Time step.

real *current_out

Pointer to the computed current value. This value needs to be computed when the voltage input condition is used.

real *voltage_out

Pointer to the computed voltage value. This value needs to be computed when the current input condition is used.

real *Qe

Heat generation rate.

Function returns

void

There are ten arguments to DEFINE_BATTERY_ECHEM_MODEL: name, zero_start, mode, temperature, voltage_in, current_in, dt, current_out, Qe, and voltage_out. You supply name, the name of the UDF. zero_start, mode, temperature, voltage_in, current_in, and dt are variables that are passed by the Ansys Fluent solver to your UDF. Your function will need to compute the values of current_out, Qe, and voltage_out.

2.7.3.3. Example

This example shows the usage of DEFINE_BATTERY_ECHEM_MODEL. The NTGK model is reproduced by using the user-defined electrochemical model.

#include "udf.h"
DEFINE_BATTERY_ECHEM_MODEL(echem_model, zero_start, mode, temperature, voltage_in, current_in, \
                           dtime, current_out, Qe, voltage_out)
{
  real DOD, U_fun, Y_fun;
  real a[]      = {4.12, -0.804, 1.075, -1.177, 0.0, 0.0};
  real b[]      = {1168.59, -8928, 52504.6, -136231, 158531.7, -67578.5};
  real T_coef[] = {1800.0, -0.00095};
  real T_ref    =  298.0;

  if (zero_start == 0) USER_DEFINED_ECHEM[0] = 0.0;
  DOD = USER_DEFINED_ECHEM[0];

  U_fun = a[0] + a[1] * DOD + a[2] * DOD * DOD + a[3] * DOD * DOD * DOD \
          + a[4] * DOD * DOD * DOD * DOD + a[5] * DOD * DOD * DOD * DOD * DOD;
  U_fun -= T_coef[1] * (temperature - T_ref);


  Y_fun = b[0] + b[1] * DOD + b[2] * DOD * DOD + b[3] * DOD * DOD * DOD \
          + b[4] * DOD * DOD * DOD * DOD + b[5] * DOD * DOD * DOD * DOD * DOD;
  Y_fun *= exp(T_coef[0] * (1. / T_ref - 1. / temperature));

  if (mode == 0)
  {
    *current_out  = Y_fun  * (U_fun - voltage_in);
    *Qe = *current_out * (U_fun - voltage_in);
    USER_DEFINED_ECHEM[0] += *current_out * dtime / (3600.0 * 14.6);
  }
  else
  {
    *voltage_out = U_fun - current_in / Y_fun;
  }
}

2.7.3.4. Hooking a DEFINE_BATTERY_ECHEM_MODEL UDF to Ansys Fluent

After the UDF that you have defined using DEFINE_BATTERY_ECHEM_MODEL is compiled (Compiling UDFs), the name of the argument that you supplied as the first DEFINE macro argument will become visible and selectable in the Battery Model dialog box (UDF tab). See Hooking Battery Model UDFs for details.

2.7.4. DEFINE_BATTERY_ELOAD_PROFILE

2.7.4.1. Description

You can use DEFINE_BATTERY_ELOAD_PROFILE to specify the electric load type and value dynamically in a simulation.

2.7.4.2. Usage

DEFINE_BATTERY_ELOAD_PROFILE (name, time, current, voltage, power, type, value)

Argument Type

Description

symbol name

UDF name.

real time

Time.

real current

System electric current.

real voltage

System electric voltage.

real power

System electric power.

int *type

Electric load type (0: C-rate, 1: Current, 2: Voltage, 3: Power, 4: External electric resistance).

real *value

Electric load value.

Function returns

void

There are seven arguments to DEFINE_BATTERY_ELOAD_PROFILE: name, time, current, voltage, power, type, and value. You supply name, the name of the UDF. time, current, voltage, power, and type are variables that are passed by the Ansys Fluent solver to your UDF. Your function will need to define the electric load type, type and its value. These two values will be returned back to the solver.

2.7.4.3. Example 1

The following example shows how to use the DEFINE_BATTERY_ELOAD_PROFILE UDF to implement an event-scheduled profile. The battery is first discharged with a constant rate 1 C until its voltage is below 3.8 V. It is put at rest for 300 seconds. Then the battery is charged with a constant rate 1 C until its voltage reaches 4.1 V. After that, the battery continues charging with a constant voltage of 4.1 V until the current is less than 5 A. Then the battery is put at rest again.

#include "udf.h"

real time0 = 0.0;
int flag = 0, flag1 = 0, flag2 = 0, flag3 = 0, flag4 = 0, flag5 = 0;
DEFINE_BATTERY_ELOAD_PROFILE(eload_profile_for_event_prof, time, current, voltage, power,
                             eload_type, eload_value)
{
/*
/*
   Note:
     1:    eload_type is an integer pointer, only takes the following values
           *eload_type = 0       C-rate type
           *eload_type = 1       current type
           *eload_type = 2       voltage type
           *eload_type = 3       power type
           *eload_type = 4       external electric resistance

     2:    using flags to control events so they get executed sequentially
*/
  real time_duration;
  time_duration = time - time0;
  if (N_ITER == 0)
  {
    flag  = 0;
    flag1 = 0;
    flag2 = 0;
    flag3 = 0;
    flag4 = 0;
    flag5 = 0;
  }

  if (flag1 == 0 || (voltage > 3.8 && flag2 == 0))
  {
    flag1 = 1;
    *eload_type = 0;
    *eload_value = 1;
    time0 =time;
  }
  else if (time_duration < 300 && flag3 == 0)
  {
    if (flag == 0)
    {
      time0 = time;
      flag = 1;
    }
    flag2 = 1;
    *eload_type = 1;
    *eload_value = 0;
  }
  else if (voltage < 4.1 && flag4 == 0)
  {
    flag3 = 1;
    *eload_type = 0;
    *eload_value = -1;
  }
  else if (current < -5 && flag5 == 0)
  {
    flag4 = 1;
    *eload_type = 2;
    *eload_value = 4.1;
  }
  else
  {
    flag5 = 1;
    *eload_type = 1;
    *eload_value = 0.0;
  }
}

2.7.4.4. Example 2

Th following example uses the battery's state of charge (SOC) to determine the charging schedule. The battery is first charged with a constant current when SOC is below 0.5. Then the battery is charged with a linearly varying current when SOC is in the range of 0.5 to 0.8. It is followed by a constant current charge in the range of 0.8 to 0.95. After that, the battery is charged with a constant voltage.

DEFINE_BATTERY_ELOAD_PROFILE function is only called from the host machine. If you want to use the battery's average temperature or SOC as a load switch condition, you need to compute average temperature or SOC in an adjust function as shown below.

#include "udf.h"

real soc = 0.0;
DEFINE_ADJUST(adjust, domain)
{
  Thread *t;
  cell_t c;
  real tmp1, tmp2;

  tmp1 = tmp2 = 0.0;
  thread_loop_c (t, domain)
  {
    if (battery_fcns->is_active_thread(t))
    {
      begin_c_loop_int(c, t)
      {
        tmp1 = C_VOLUME(c, t) * (1.0 - C_BATTERY_DISCHARGE_DEPTH(c, t));
        tmp2 = C_VOLUME(c, t);
      }
      end_c_loop_int(c, t)
    }
  }
  tmp1 = PRF_GRSUM1(tmp1);
  tmp2 = PRF_GRSUM1(tmp2);
  soc = tmp1/ tmp2;
  node_to_host_real_1(soc);
}

DEFINE_BATTERY_ELOAD_PROFILE(eload_profile_for_cfd, time, current, voltage, power, eload_type, eload_value)
{
  if (soc < 0.5)
  {
    *eload_type = 1;
    *eload_value = -45.0;
  }
  else if (soc >=0.5 && soc <0.8)
  {
    *eload_type = 1;
    *eload_value = -45.0 + (-15.0 + 45.0) / (0.8 - 0.5) * (soc - 0.5);
  }
  else if (soc >= 0.8 && soc < 0.95)
  {
    *eload_type = 1;
    *eload_value = -15.0;
  }
  else
  {
    *eload_type = 2;
    *eload_value = 4.12;
  }
}

2.7.4.5. Hooking a DEFINE_BATTERY_ELOAD_PROFILE UDF to Ansys Fluent

After the UDF that you have defined using DEFINE_BATTERY_ELOAD_PROFILE is compiled (Compiling UDFs), the name of the argument that you supplied as the first DEFINE macro argument will become visible and selectable in the Battery Model dialog box (Model Options tab). See Hooking Battery Model UDFs for details.

2.7.5. DEFINE_BATTERY_ENTROPIC_HEAT

2.7.5.1. Description

You can use DEFINE_BATTERY_ENTROPIC_HEAT to compute the entropic heat term in the battery thermal analysis if you want to include the entropic heat effect in your simulation. The entropic heat can be included in all the battery submodels including the NTGK, ECM and Newman's P2D models.

2.7.5.2. Usage

DEFINE_BATTERY_ENTROPIC_HEAT (name, T, soc, discharge_mode)

Argument Type

Description

symbol name

UDF name.

real T

Temperature.

real soc

State of the charge (SOC).

int discharge_mode

Flag with a value of 0 or 1. 0 indicates charging, and 1 indicates discharging.

Function returns

real

There are four arguments to DEFINE_BATTERY_ENTROPIC_HEAT: name, T, soc, and discharge_mode. You supply name, the name of the UDF. T, soc, and discharge_mode are variables that are passed by the Ansys Fluent solver to your UDF. Your function will return a value of the term in the entropic heat calculation (see Equation 19–8, Equation 19–13, and Equation 19–30 in the Fluent Theory Guide).

2.7.5.3. Example

The entropic heat is ignored in the default Ansys Fluent battery model, which corresponds to =0. This example shows how to use DEFINE_BATTERY_ENTROPIC_HEAT to compute the term in the entropic heat calculation.

#include "udf.h"
real interpolate_table(int N_p, real *soc_data, real *value, real SOC)
{
   int i;
   real result= 0.0;
   if (SOC < soc_data[0])
      result = value[0];
   else if (SOC > soc_data[N_p - 1])
      result = value[N_p -1];
   else
   {
     for (i=0; i<N_p-1; i++)
       if (SOC >=  soc_data[i] && SOC <=  soc_data[i+1])
       {
         result = value[i] + (value[i+1]-value[i])/(soc_data[i+1]-soc_data[i])*(SOC-soc_data[i]);
         break;
       }
   }
   return result;
}

DEFINE_BATTERY_ENTROPIC_HEAT(entropic_heat, T, SOC, discharging_mode)
{
   real tmp1, tmp2, dUdT = 0.0;
   real T1= 300, T2=320;
   real soc_data1[] = {0.0, 0.23, 0.28, 0.35, 0.47, 0.56, 0.82, 1.0};
   real value1[] = {-0.3, -0.03, 0.14, 0.14, -0.31, 0.05, 0.22, 0.22};
   real soc_data2[] = {0.0, 1.0};
   real value2[] = {0, 1};
   int i, N_p1 = 8, N_p2 = 2;

   for (i=0; i<N_p1; i++)
      value1[i] *= 0.0001;
   for (i=0; i<N_p2; i++)
      value2[i] *= 0.0001;

   if (T<T1)
      dUdT = interpolate_table(N_p1, soc_data1, value1, SOC);
   else if (T>T2)
      dUdT = interpolate_table(N_p2, soc_data2, value2, SOC);
   else
   {
     tmp1 = interpolate_table(N_p1, soc_data1, value1, SOC);
     tmp2 = interpolate_table(N_p2, soc_data2, value2, SOC);
     dUdT = tmp1 + (tmp2 -tmp1)/(T2 -T1) * (T-T1);
    }
   return dUdT;
}

2.7.5.4. Hooking a DEFINE_BATTERY_ENTROPIC_HEAT UDF to Ansys Fluent

After the UDF that you have defined using DEFINE_BATTERY_ENTROPIC_HEAT is compiled (Compiling UDFs), the name of the argument that you supplied as the first DEFINE macro argument will become visible and selectable in the Battery Model dialog box (UDF tab). See Hooking Battery Model UDFs for details.

2.7.6. DEFINE_BATTERY_NEWMAN_BV_RATE

2.7.6.1. Description

You can use DEFINE_BATTERY_NEWMAN_BV_RATE to customize the Butler-Volmer rate used in the Newman's P2D model. See Newman’s P2D Model in the Fluent Theory Guide for more information.

2.7.6.2. Usage

DEFINE_BATTERY_NEWMAN_BV_RATE (name, Ce, Cs, Cs_max, T, eta, k_m, alpha_a, alpha_c, mode)

Argument Type

Description

symbol name

UDF name.

real Ce

Lithium ion concentration in electrolyte.

real Cs

Lithium concentration in electrode.

real Cs_max

Maximum lithium concentration in electrode.

real T

Temperature.

real eta

Overpotential ().

real k_m

Rate pre-exponential factor.

real alpha_a

Anodic charge transfer coefficient.

real alpha_c

Cathodic charge transfer coefficient.

int mode

Flag to indicate whether the reaction is in anode or cathode. A value of 0 indicates anode, and a value of 1 indicates cathode.

Function returns

real

There are ten arguments to DEFINE_BATTERY_NEWMAN_BV_RATE: name, Ce, Cs, Cs_max, T, eta, k_m, alpha_a, alpha_c, and mode. You supply name, the name of the UDF. Ce, Cs, Cs_max, T, eta, k_m, alpha_a, alpha_c, and mode are variables that are passed by the Ansys Fluent solver to your UDF. Your function will return the Butler-Volmer rate.

2.7.6.3. Example

This example shows the usage of DEFINE_BATTERY_NEWMAN_BV_RATE to compute the electrochemical reaction rate for both cathode and anode using the default Butler-Volmer equations with the kinetics parameters.

#include "udf.h"
DEFINE_BATTERY_NEWMAN_BV_RATE(p2d_bv_rate, Ce, Cs, Cs_max, T, eta, k_m, alpha_a, alpha_c, mode)
{
   real rate, i_0;
   i_0 = k_m * pow(Ce, alpha_a)  * pow(Cs, alpha_c) * pow(Cs_max - Cs, alpha_a);
   rate = i_0 * (exp(alpha_a * 9.6485e4 / (8.314 * T) * eta) - exp(-alpha_c * 9.6485e4/(8.314*T)*eta));
   return rate;
}

2.7.6.4. Hooking a DEFINE_BATTERY_NEWMAN_BV_RATE UDF to Ansys Fluent

After the UDF that you have defined using DEFINE_BATTERY_NEWMAN_BV_RATE is compiled (Compiling UDFs), the name of the argument that you supplied as the first DEFINE macro argument will become visible and selectable in the Battery Model dialog box (Advanced tab). See Hooking Battery Model UDFs for details.

2.7.7. DEFINE_BATTERY_NEWMAN_POSTPROCESSING

2.7.7.1. Description

You can use DEFINE_BATTERY_NEWMAN_POSTPROCESSING to export the detailed information of the Newman's P2D model results. See Newman’s P2D Model in the Fluent Theory Guide for more information.

2.7.7.2. Usage

DEFINE_BATTERY_NEWMAN_POSTPROCESSING (name, c, t, T, Vp, Vn)

Argument Type

Description

symbol name

UDF name.

real c

Index of the cell calling the function.

Thread *t

Pointer to the thread of the function calling cell.

real T

Temperature.

real Vp

Cathode potential of the electrode.

real Vn

Anode potential of the electrode.

Function returns

void

There are six arguments to DEFINE_BATTERY_NEWMAN_POSTPROCESSING: name, c, t, T, Vp, and Vn. You supply name, the name of the UDF. c, t, T, Vp, and Vn are variables that are passed by the Ansys Fluent solver to your UDF. You can use the UDF to export information such as potential and lithium concentration to a file or print it in the console window.

2.7.7.3. Example

This example shows how to use DEFINE_BATTERY_NEWMAN_POSTPROCESSING to print some fundamental variables of the Newman's P2D model to the console window.

The function is called every time the Newman's P2D solver is called. The UDF prints a large amount of information. You may want to add some controls to print or save only selected variables.

#include "udf.h"
DEFINE_BATTERY_NEWMAN_POSTPROCESSING(p2d_output, c, t, T, Vp, Vn)
{
    int i, j;

    Message(" Newman model results for cell %d of Thread_id %d at Time=%f\n", c, \
              NNULLP (t) ? THREAD_ID(t) : -1, CURRENT_TIME);
    Message(" T=%f Vp=%f Vn=%f \n", T, Vp, Vn);

    Message(" Grid center location\n");
    Message("NE\n");
    for (i = 0; i < battery_n_XN; i++) Message(" %g\n", battery_X_cv_NE[i]);
    Message("SP\n");
    for (i = 0; i < battery_n_XS; i++) Message(" %g\n", battery_X_cv_SP[i]);
    Message("PE\n");
    for (i = 0; i < battery_n_XP; i++) Message(" %g\n", battery_X_cv_PE[i]);

    {
      Message("RP\n");
      for (i = 0; i < battery_n_RP; i++) Message(" %g\n", battery_R_cv_PE[i]);
      Message("RN\n");
      for (i = 0; i < battery_n_RN; i++) Message(" %g\n", battery_R_cv_NE[i]);
    }

    Message("Positive Electrode: battery_C_CS_P and battery_C_CE_P \n");
    for (i = 0; i < battery_n_XP; i++)
    {
      for (j = 0; j < battery_n_RP; j++)
      {
        Message("%12.5e  ", battery_CsPE[i][j]);
      }
      Message("\n");
      Message("%12.5e\n",  battery_CePE[i]);
    }

    Message("Separator  battery_C_CE \n");
    for (i = 0; i < battery_n_XS; i++)
    {
      Message(" %12.5e\n", battery_CeSP[i]);
    }

    Message("Negative Electrode: battery_C_CS_N and battery_C_CE_N \n");
    for (i = 0; i < battery_n_XN; i++)
    {
      for (j = 0; j < battery_n_RN; j++)
      {
        Message("%12.5e  ", battery_CsNE[i][j]);
      }
      Message("\n");
      Message("%12.5e\n",  battery_CeNE[i]);
    }

    Message("potential profile in electrolyte\n");
    for (i = 0; i < battery_n_XN; i++)
      Message(" %le \n", battery_PhieNE[i]);
    for (i = 0; i < battery_n_XS; i++)
      Message(" %le \n", battery_PhieSP[i]);
    for (i = 0; i < battery_n_XP; i++)
      Message(" %le \n", battery_PhiePE[i]);

    Message("potential profile in electrode\n");
    for (i = 0; i < battery_n_XN; i++)
      Message(" %le \n", battery_PhisNE[i]);
    for (i = 0; i < battery_n_XP; i++)
      Message(" %le \n", battery_PhisPE[i]);


    for (i = 0; i < battery_n_XN; i++)
      Message(" %12.5e %12.5e %12.5e %12.5e %12.5e %12.5e\n", battery_kappa_NE[i], battery_diff_NE[i], \
              battery_t_plus_NE[i], battery_kappa2_NE[i], battery_eta_NE[i], battery_i_NE[i]);
    for (i = 0; i < battery_n_XS; i++)
      Message(" %12.5e %12.5e %12.5e %12.5e\n", battery_kappa_SP[i], battery_diff_SP[i], \
                battery_t_plus_SP[i], battery_kappa2_SP[i]);
    for (i = 0; i < battery_n_XP; i++)
      Message(" %12.5e %12.5e %12.5e %12.5e %12.5e %12.5e\n", battery_kappa_PE[i], battery_diff_PE[i], \
              battery_t_plus_PE[i], battery_kappa2_PE[i], battery_eta_PE[i], battery_i_PE[i]);

   return ;
}

2.7.7.4. Hooking a DEFINE_BATTERY_NEWMAN_POSTPROCESSING UDF to Ansys Fluent

After the UDF that you have defined using DEFINE_BATTERY_NEWMAN_POSTPROCESSING is compiled (Compiling UDFs), the name of the argument that you supplied as the first DEFINE macro argument will become visible and selectable in the Battery Model dialog box (UDF tab). See Hooking Battery Model UDFs for details.

2.7.8. DEFINE_BATTERY_PARAMETER_ECM

2.7.8.1. Description

You can use DEFINE_BATTERY_PARAMETER_ECM to specify your own parameters for the ECM model. See ECM Model in the Fluent Theory Guide for details.

2.7.8.2. Usage

DEFINE_BATTERY_PARAMETER_ECM (name, c, t, T, soc, mode, Voc, Rs, R1, C1, R2, C2, R3, C3)

Argument Type

Description

symbol name

UDF name.

cell_t c

Cell index.

Thread *t

Pointer to the thread of the active zone.

int mode

Integer flag that indicates charging/discharging mode. A value of 1 indicates discharging, while a value of 0 indicates charging.

real T

Temperature.

real soc

Value of the state of the charge (SOC).

real *Voc

Pointer to the Voc value.

real *RS

Pointer to the Rs value.

real *R1

Pointer to the R1 value.

real *C1

Pointer to the C1 value.

real *R2

Pointer to the R2 value.

real *C2

Pointer to the C2 value.

real *R3

Pointer to the R3 value.

real *C3

Pointer to the C3 value.

Function returns

void

There are fourteen arguments to DEFINE_BATTERY_PARAMETER_ECM: name, c, t, T, soc, mode, Voc, Rs, R1, C1, R2, C2, R3, and C3. You will supply name, the name of the UDF. c, t, T, soc, and mode are variables that are passed by the Ansys Fluent solver to your UDF. Your function will need to compute the values of Voc, Rs, R1, C1, R2, C2, R3, and C3.

2.7.8.3. Example

This example shows how to use DEFINE_BATTERY_PARAMETER_ECM to reproduce the default polynomial functions in Chen's form.

The UDF uses a 3 RC loop circuit. The default Chen's circuit uses only 2 RC loops. Small values of R3 and C3 are used to skip the third RC loop.

#include "udf.h"
DEFINE_BATTERY_PARAMETER_ECM(ecm_model_parameter, c, t, T, soc, mode, Voc, RRs, RR1, CC1, RR2, CC2, RR3, CC3)
{
  *Voc = 3.685 - 1.031*exp(-35.0*soc) + 0.2156*soc - 0.1178*soc*soc + 0.3201*soc*soc*soc;
  *RRs = 0.07446 + 0.1562*exp(-24.37*soc);
  *RR1    = 0.04669 + 0.3208*exp(-29.14*soc);
  *RR2    = 0.04984 + 6.603*exp(-155.2*soc);
  *CC1    = 703.6   - 752.9*exp(-13.51*soc);
  *CC2    = 4475.0  - 6056.*exp(-27.12*soc);
  *RR3    = 1.0e-5;
  *CC3    = 1.0e-5;
}

2.7.8.4. Hooking a DEFINE_BATTERY_PARAMETER_ECM UDF to Ansys Fluent

After the UDF that you have defined using DEFINE_BATTERY_PARAMETER_ECM is compiled (Compiling UDFs), the name of the argument that you supplied as the first DEFINE macro argument will become visible and selectable in the Battery Model dialog box (UDF tab). See Hooking Battery Model UDFs for details.

2.7.9. DEFINE_BATTERY_PARAMETER_NTGK

2.7.9.1. Description

You can use DEFINE_BATTERY_PARAMETER_NTGK to specify your own U and Y functions used in the NTGK model. See NTGK/DCIR Model in the Fluent Theory Guide for details.

2.7.9.2. Usage

DEFINE_BATTERY_PARAMETER_NTGK (name, c, t, T, soc, U, Y)

Argument Type

Description

symbol name

UDF name.

cell_t c

Cell index.

Thread *t

Pointer to the thread of the active zone.

real *T

Temperature.

real soc

Value of the state of charge (SOC).

real *U

Pointer to the value of U.

real *Y

Pointer to the value of Y.

Function returns

void

There are seven arguments to DEFINE_BATTERY_PARAMETER_NTGK: name, c, t, T, soc, U, and Y. You will supply name, the name of the UDF. c, t, T, and soc are variables that are passed by the Ansys Fluent solver to your UDF. Your function will need to compute the values of U and Y.

2.7.9.3. Example

This example shows how to use DEFINE_BATTERY_PARAMETER_NTGK to reproduce the default polynomial U and Y functions.

#include "udf.h"
DEFINE_BATTERY_PARAMETER_NTGK(ntgk_model_parameter, c, t, T, soc, U, Y)
{
  real a[] = {4.12, -0.804, 1.075, -1.177, 0.0, 0.0};
  real b[] = {1168.59, -8928, 52504.6, -136231, 158531.7, -67578.5};
  real C[] = {1800.0, -0.00095};
  real DOD = 1.0 - soc;
  real T_ref = 298.0;

  *U = a[0]+a[1]*DOD+a[2]*DOD*DOD+a[3]*DOD*DOD*DOD \
       + a[4]*DOD*DOD*DOD*DOD + a[5]*DOD*DOD*DOD*DOD*DOD;
  *U -= C[1]*(T - T_ref);

  *Y = b[0]+b[1]*DOD+b[2]*DOD*DOD+b[3]*DOD*DOD*DOD \
       + b[4]*DOD*DOD*DOD*DOD+b[5]*DOD*DOD*DOD*DOD*DOD;

  *Y *= exp(C[0]*(1./T_ref - 1./T)));
}

2.7.9.4. Hooking a DEFINE_BATTERY_PARAMETER_NTGK UDF to Ansys Fluent

After the UDF that you have defined using DEFINE_BATTERY_PARAMETER_NTGK is compiled (Compiling UDFs), the name of the argument that you supplied as the first DEFINE macro argument will become visible and selectable in the Battery Model dialog box (UDF tab). See Hooking Battery Model UDFs for details.

2.7.10. DEFINE_BATTERY_PROPERTY

2.7.10.1. Description

You can use DEFINE_BATTERY_PROPERTY to specify material properties used in the Newman's P2D model. See Newman’s P2D Model in the Fluent Theory Guide for more information.

2.7.10.2. Usage

DEFINE_BATTERY_PROPERTY (name, x, T)

Argument Type

Description

symbol name

UDF name.

real x

Dependent variable of material property.

real T

Temperature.

Function returns

real

There are three arguments to DEFINE_BATTERY_PROPERTY: name, x, and T. You supply name, the name of the UDF. x and T are variables that are passed by the Ansys Fluent solver to your UDF. These are the variables the material property depends on. For example, if the UDF is used to define open circuit potential, then x will be the state of lithiation (sol) of the electrode, that is, the ratio of the lithium concentration at the electrode surface and the maximum electrode concentration. If the UDF is used to define any electrolyte property, then x will be the lithium concentration in the electrolyte. If the UDF is used for any solid electrode property, then x will be the lithium concentration in the electrode. Your function will return a value of the material property.

2.7.10.3. Example

This example shows the usage of DEFINE_BATTERY_PROPERTY. The first two UDFs are used to compute the open circuit potential used for the cathode and anode electrode. And the last one is used to compute the ionic conductivity of the electrolyte material. The UDFs are used to reproduce the default settings used in the Newman's P2D model.

#include "udf.h"

DEFINE_BATTERY_PROPERTY(ocp_p, x, T)
{
  real UPE, xx;
  xx = -14.555 * x + 8.609;
  xx *= 2.0;
  UPE = 4.199 + 0.0566 * (exp(xx) - 1.0) / (exp(xx) + 1.0)
          - 0.0275 * (pow(0.998 - x, -0.492) - 1.901)
          - 0.1570 * exp(-0.0474 * pow(x, 8.0))
          + 0.8100 * exp(-40.0 * (x - 0.134));
   return UPE;
}

DEFINE_BATTERY_PROPERTY(ocp_n, x, T)
{
  real UNE = -0.16 + 1.32 * exp(-3.0 * x) + 10.0 * exp(-2000.0 * x);
  return UNE;
}

DEFINE_BATTERY_PROPERTY(kappa, ce, T)
{
  return 1.0793e-2 + (6.7461e-4) * ce - (5.2245e-7) * ce * ce
          + (1.3605e-10) * ce * ce * ce - (1.1724e-14) * ce * ce * ce * ce;
}

2.7.10.4. Hooking a DEFINE_BATTERY_PROPERTY UDF to Ansys Fluent

After the UDF that you have defined using DEFINE_BATTERY_PROPERTY is compiled (Compiling UDFs), the name of the argument that you supplied as the first DEFINE macro argument will become visible and selectable in the Battery Model dialog box (Model Parameter tab). See Hooking Battery Model UDFs for details.

2.7.11. DEFINE_BATTERY_SWELL_LAYER_N

2.7.11.1. Description

You can use DEFINE_BATTERY_SWELL_LAYER_N to specify your own normal vector to the battery electrode layer for the battery swelling model. See Battery Swelling Model in the Fluent Theory Guide for more information.

2.7.11.2. Usage

DEFINE_BATTERY_SWELL_LAYER_N (name, c, t, N_vec)

Argument Type

Description

symbol name

UDF name.

cell_t c

Cell index.

Thread *t

Pointer to the thread of the active zone.

real *N_vec

Pointer to the normal vector.

Function returns

void

There are four arguments to DEFINE_BATTERY_SWELL_LAYER_N: name, c, t, and N_vec. You supply name, the name of the UDF. c, and t are variables that are passed by the Ansys Fluent solver to your UDF. Your function will need to specify three components of the normal vector N_vec of the battery electrode layer and pass it back to the solver. The magnitude of the specified normal vector does not have to be unity as the Ansys Fluent solver automatically performs vector normalization.

2.7.11.3. Example

In this example, DEFINE_BATTERY_SWELL_LAYER_N specifies the normal vector to the battery electrode layer. The battery cell is cylindrical with its axis coinciding with the Z axis. The normal vector to the electrode layer is in the radial direction of the cylinder.

#include "udf.h"

DEFINE_BATTERY_SWELL_LAYER_N(myLayer, c, t, N_vec)
{
  real x_cell_center[ND_ND];

  C_CENTROID(x_cell_center, c, t);

  N_vec[0] = x_cell_center[0];
  N_vec[1] = x_cell_center[1];
  N_vec[2] = 0.0;
}

2.7.11.4. Hooking a DEFINE_BATTERY_SWELL_LAYER_N UDF to Ansys Fluent

After the UDF that you have defined using DEFINE_BATTERY_SWELL_LAYER_N is compiled (Compiling UDFs), the name of the argument that you supplied as the first DEFINE macro argument will become visible and selectable in the Battery Model dialog box (Model Parameters tab). See Hooking Battery Model UDFs for details.

2.7.12. DEFINE_BATTERY_SWELL_STRAIN

2.7.12.1. Description

You can use DEFINE_BATTERY_SWELL_STRAIN to customize the swelling strain used in the empirical battery swelling model. See Empirical-Based Swelling Model in the Fluent Theory Guide for more information.

2.7.12.2. Usage

DEFINE_BATTERY_SWELL_STRAIN (name, c, t, T, soc, current)

Argument Type

Description

symbol name

UDF name.

cell_t c

Cell index.

Thread *t

Pointer to the thread of the battery active zone.

real T

Temperature.

real soc

State of the charge (SOC) in the battery cell.

real current

Current transfer density in a cell.

Function returns

real

There are six arguments to DEFINE_BATTERY_SWELL_STRAIN: name, c, t, T, soc, and current. You supply name, the name of the UDF. c, t, T, soc, and current are variables that are passed by the Ansys Fluent solver to your UDF. These are the variables that you can use to define the swelling strain. Your function will return a value of the swell strain.

2.7.12.3. Example

The following example provides the source code of the default equation used in Ansys Fluent simulations when you do not use a DEFINE_BATTERY_SWELL_STRAIN. You can modify this template to adapt it to your needs.

#include "udf.h"

DEFINE_BATTERY_SWELL_STRAIN(swell_rate, c, t, T, soc, current)
{
  real omega = 0.2, soc_ref = 0.25;
  return omega * (soc - soc_ref) / (1.0 + omega * soc_ref);
}

2.7.12.4. Hooking a DEFINE_BATTERY_PROPERTY UDF to Ansys Fluent

After the UDF that you have defined using DEFINE_BATTERY_SWELL_STRAIN is compiled (Compiling UDFs), the name of the argument that you supplied as the first DEFINE macro argument will become visible and selectable in the Swelling Model Parameters dialog box. See Hooking Battery Model UDFs for details.