void
AddCoupledSolidKinSpeciesAction::act()
{
  mooseDoOnce(printReactions());

  std::vector<bool> primary_participation(_primary_species.size(), false);
  std::vector<std::string> solid_kin_species(_reactions.size());
  std::vector<Real> weight;

  // Loop through reactions
  for (unsigned int j = 0; j < _reactions.size(); ++j)
  {
    std::vector<std::string> tokens;

    // Parsing each reaction
    MooseUtils::tokenize(_reactions[j], tokens, 1, "+=");
    if (tokens.size() == 0)
      mooseError("Empty reaction specified.");

    std::vector<Real> stos(tokens.size() - 1);
    std::vector<VariableName> rxn_species(tokens.size() - 1);

    for (unsigned int k = 0; k < tokens.size(); ++k)
    {
      std::vector<std::string> stos_primary_species;
      MooseUtils::tokenize(tokens[k], stos_primary_species, 1, "()");
      if (stos_primary_species.size() == 2)
      {
        Real coef;
        std::istringstream iss(stos_primary_species[0]);
        iss >> coef;
        stos[k] = coef;
        rxn_species[k] = stos_primary_species[1];

        // Check the participation of primary species
        for (unsigned int i = 0; i < _primary_species.size(); ++i)
          if (rxn_species[k] == _primary_species[i])
            primary_participation[i] = true;
      }
      else
        solid_kin_species[j] = stos_primary_species[0];
    }
void
AddCoupledSolidKinSpeciesKernelsAction::act()
{
  std::vector<NonlinearVariableName> vars = getParam<std::vector<NonlinearVariableName> >("primary_species");
  std::vector<std::string> reactions = getParam<std::vector<std::string> >("kin_reactions");

  Moose::out<< "Solid kinetic reaction list:" << "\n";
  for (unsigned int i=0; i < reactions.size(); i++)
  {
    Moose::out<< reactions[i] << "\n";
  }

  for (unsigned int i=0; i < vars.size(); i++)
  {
    Moose::out << "primary species - " << vars[i] << "\n";
    std::vector<bool> primary_participation(reactions.size(), false);
    std::vector<std::string> solid_kin_species(reactions.size());
    std::vector<Real> weight;

    for (unsigned int j=0; j < reactions.size(); j++)
    {
      std::vector<std::string> tokens;

      // Parsing each reaction
      MooseUtils::tokenize(reactions[j], tokens, 1, "+=");

      std::vector<Real> stos(tokens.size()-1);
      std::vector<std::string> rxn_vars(tokens.size()-1);

      for (unsigned int k=0; k < tokens.size(); k++)
      {
        Moose::out << tokens[k] << "\t";
        std::vector<std::string> stos_vars;
        MooseUtils::tokenize(tokens[k], stos_vars, 1, "()");
        if (stos_vars.size() == 2)
        {
          Real coef;
          std::istringstream iss(stos_vars[0]);
          iss >> coef;
          stos[k] = coef;
          rxn_vars[k] = stos_vars[1];
          Moose::out << "stochiometric: " << stos[k] << "\t";
          Moose::out << "reactant: " << rxn_vars[k] << "\n";
          // Check the participation of primary species
          if (rxn_vars[k] == vars[i]) primary_participation[j] = true;
        }
        else
        {
          solid_kin_species[j] = stos_vars[0];
        }
      }
      // Done parsing, recorded stochiometric and variables into separate arrays
      Moose::out << "whether primary present (0 is not): " << primary_participation[j] << "\n";


      if (primary_participation[j])
      {
        // Assigning the stochiometrics based on parsing
        for (unsigned int m=0; m < rxn_vars.size(); m++)
        {
          if (rxn_vars[m] == vars[i])
          {
            weight.push_back(stos[m]);
            Moose::out << "weight for " << rxn_vars[m] <<" : " << weight[weight.size()-1] << "\n";
          }
        }
        Moose::out << "solid kinetic species: " << solid_kin_species[j] << "\n";

        std::vector<VariableName> coupled_var(1);
        coupled_var[0] = solid_kin_species[j];

        // Building kernels for solid kinetic species
        InputParameters params_kin = _factory.getValidParams("CoupledBEKinetic");
        params_kin.set<NonlinearVariableName>("variable") = vars[i];
        params_kin.set<std::vector<Real> >("weight") = weight;
        params_kin.set<std::vector<VariableName> >("v") = coupled_var;
        _problem->addKernel("CoupledBEKinetic", vars[i]+"_"+solid_kin_species[j]+"_kin", params_kin);

        Moose::out << vars[i]+"_"+solid_kin_species[j]+"_kin" << "\n";
        params_kin.print();
      }
    }
void
AddCoupledEqSpeciesKernelsAction::act()
{
  // Reading primary species and reaction network from the input file
  std::vector<NonlinearVariableName> vars =
      getParam<std::vector<NonlinearVariableName>>("primary_species");
  std::string reactions = getParam<std::string>("reactions");

  // Getting ready for the parsing system
  pcrecpp::RE re_reactions(
      "(.*?)" // the reaction network (any character until the equilibrium coefficient appears)
      "\\s"   // word boundary
      "("     // start capture
      "-?"    // optional minus sign
      "\\d+(?:\\.\\d*)?" // digits followed by optional decimal and more 0 or more digits
      ")"
      "\\b"        // word boundary
      "(?:\\s+|$)" // eat the whitespace
      ,
      pcrecpp::RE_Options().set_extended(true));

  pcrecpp::RE re_terms("(\\S+)");
  pcrecpp::RE re_coeff_and_species("(?: \\(? (.*?) \\)? )" // match the leading coefficent
                                   "([A-Za-z].*)"          // match the species
                                   ,
                                   pcrecpp::RE_Options().set_extended(true));

  pcrecpp::StringPiece input(reactions);

  pcrecpp::StringPiece single_reaction, term;
  Real equal_coeff;

  std::vector<std::vector<bool>> primary_participation(vars.size());
  std::vector<string> eq_species;
  std::vector<Real> weight;
  std::vector<Real> eq_const;
  std::vector<std::vector<Real>> sto_u(vars.size());
  std::vector<std::vector<std::vector<Real>>> sto_v(vars.size());
  std::vector<std::vector<std::vector<VariableName>>> coupled_v(vars.size());

  std::vector<std::vector<Real>> stos;
  std::vector<std::vector<std::string>> primary_species_involved;

  unsigned int n_reactions = 0;

  // Start parsing
  // Going into every single reaction
  std::ostringstream oss;

  while (re_reactions.FindAndConsume(&input, &single_reaction, &equal_coeff))
  {
    n_reactions += 1;
    oss << "\n\n" << n_reactions << "_th reaction: " << single_reaction << std::endl;

    eq_const.push_back(equal_coeff);
    oss << "\nEquilibrium: " << eq_const[n_reactions - 1] << std::endl;

    // capture all of the terms
    std::string species, coeff_str;
    Real coeff;
    int sign = 1;
    bool secondary = false;

    std::vector<Real> local_stos;
    std::vector<std::string> local_species_list;

    // Going to find every single term in this reaction, sto_species combos and operators
    while (re_terms.FindAndConsume(&single_reaction, &term))
    {
      // Separating the sto from species
      if (re_coeff_and_species.PartialMatch(term, &coeff_str, &species))
      {
        if (coeff_str.length())
        {
          std::istringstream iss(coeff_str);
          iss >> coeff;
        }
        else
          coeff = 1.0;

        coeff *= sign;

        if (secondary)
          eq_species.push_back(species);
        else
        {
          local_stos.push_back(coeff);
          local_species_list.push_back(species);
          oss << "\nSpecies: " << species << "\n"
              << "Coeff: " << coeff << std::endl;
        }
      }
      // Finding the operators and assign value of -1.0 to "-" sign
      else if (term == "+" || term == "=" || term == "-")