bool is_lt(expr const & a, expr const & b, bool use_hash) { if (is_eqp(a, b)) return false; unsigned wa = get_weight(a); unsigned wb = get_weight(b); if (wa < wb) return true; if (wa > wb) return false; if (a.kind() != b.kind()) return a.kind() < b.kind(); if (use_hash) { if (a.hash() < b.hash()) return true; if (a.hash() > b.hash()) return false; } if (a == b) return false; switch (a.kind()) { case expr_kind::Var: return var_idx(a) < var_idx(b); case expr_kind::Constant: if (const_name(a) != const_name(b)) return const_name(a) < const_name(b); else return is_lt(const_levels(a), const_levels(b), use_hash); case expr_kind::App: if (app_fn(a) != app_fn(b)) return is_lt(app_fn(a), app_fn(b), use_hash); else return is_lt(app_arg(a), app_arg(b), use_hash); case expr_kind::Lambda: case expr_kind::Pi: if (binding_domain(a) != binding_domain(b)) return is_lt(binding_domain(a), binding_domain(b), use_hash); else return is_lt(binding_body(a), binding_body(b), use_hash); case expr_kind::Let: if (let_type(a) != let_type(b)) return is_lt(let_type(a), let_type(b), use_hash); else if (let_value(a) != let_value(b)) return is_lt(let_value(a), let_value(b), use_hash); else return is_lt(let_body(a), let_body(b), use_hash); case expr_kind::Sort: return is_lt(sort_level(a), sort_level(b), use_hash); case expr_kind::Local: case expr_kind::Meta: if (mlocal_name(a) != mlocal_name(b)) return mlocal_name(a) < mlocal_name(b); else return is_lt(mlocal_type(a), mlocal_type(b), use_hash); case expr_kind::Macro: if (macro_def(a) != macro_def(b)) return macro_def(a) < macro_def(b); if (macro_num_args(a) != macro_num_args(b)) return macro_num_args(a) < macro_num_args(b); for (unsigned i = 0; i < macro_num_args(a); i++) { if (macro_arg(a, i) != macro_arg(b, i)) return is_lt(macro_arg(a, i), macro_arg(b, i), use_hash); } return false; } lean_unreachable(); // LCOV_EXCL_LINE }
bool apply(expr const & a, expr const & b) { if (is_eqp(a, b)) return true; if (a.hash() != b.hash()) return false; if (a.kind() != b.kind()) return false; if (is_var(a)) return var_idx(a) == var_idx(b); if (m_cache.check(a, b)) return true; switch (a.kind()) { case expr_kind::Var: lean_unreachable(); // LCOV_EXCL_LINE case expr_kind::Constant: return const_name(a) == const_name(b) && compare(const_levels(a), const_levels(b), [](level const & l1, level const & l2) { return l1 == l2; }); case expr_kind::Meta: return mlocal_name(a) == mlocal_name(b) && apply(mlocal_type(a), mlocal_type(b)); case expr_kind::Local: return mlocal_name(a) == mlocal_name(b) && apply(mlocal_type(a), mlocal_type(b)) && (!CompareBinderInfo || local_pp_name(a) == local_pp_name(b)) && (!CompareBinderInfo || local_info(a) == local_info(b)); case expr_kind::App: check_system(); return apply(app_fn(a), app_fn(b)) && apply(app_arg(a), app_arg(b)); case expr_kind::Lambda: case expr_kind::Pi: check_system(); return apply(binding_domain(a), binding_domain(b)) && apply(binding_body(a), binding_body(b)) && (!CompareBinderInfo || binding_name(a) == binding_name(b)) && (!CompareBinderInfo || binding_info(a) == binding_info(b)); case expr_kind::Let: check_system(); return apply(let_type(a), let_type(b)) && apply(let_value(a), let_value(b)) && apply(let_body(a), let_body(b)) && (!CompareBinderInfo || let_name(a) == let_name(b)); case expr_kind::Sort: return sort_level(a) == sort_level(b); case expr_kind::Macro: check_system(); if (macro_def(a) != macro_def(b) || macro_num_args(a) != macro_num_args(b)) return false; for (unsigned i = 0; i < macro_num_args(a); i++) { if (!apply(macro_arg(a, i), macro_arg(b, i))) return false; } return true; } lean_unreachable(); // LCOV_EXCL_LINE }
bool expr_eq_fn::apply(expr const & a, expr const & b) { if (is_eqp(a, b)) return true; if (a.hash() != b.hash()) return false; if (a.kind() != b.kind()) return false; if (is_var(a)) return var_idx(a) == var_idx(b); if (m_counter >= LEAN_EQ_CACHE_THRESHOLD && is_shared(a) && is_shared(b)) { auto p = std::make_pair(a.raw(), b.raw()); if (!m_eq_visited) m_eq_visited.reset(new expr_cell_pair_set); if (m_eq_visited->find(p) != m_eq_visited->end()) return true; m_eq_visited->insert(p); } check_system("expression equality test"); switch (a.kind()) { case expr_kind::Var: lean_unreachable(); // LCOV_EXCL_LINE case expr_kind::Constant: return const_name(a) == const_name(b) && compare(const_levels(a), const_levels(b), [](level const & l1, level const & l2) { return l1 == l2; }); case expr_kind::Local: case expr_kind::Meta: return mlocal_name(a) == mlocal_name(b) && apply(mlocal_type(a), mlocal_type(b)); case expr_kind::App: m_counter++; return apply(app_fn(a), app_fn(b)) && apply(app_arg(a), app_arg(b)); case expr_kind::Lambda: case expr_kind::Pi: m_counter++; return apply(binding_domain(a), binding_domain(b)) && apply(binding_body(a), binding_body(b)) && (!m_compare_binder_info || binding_info(a) == binding_info(b)); case expr_kind::Sort: return sort_level(a) == sort_level(b); case expr_kind::Macro: m_counter++; if (macro_def(a) != macro_def(b) || macro_num_args(a) != macro_num_args(b)) return false; for (unsigned i = 0; i < macro_num_args(a); i++) { if (!apply(macro_arg(a, i), macro_arg(b, i))) return false; } return true; case expr_kind::Let: m_counter++; return apply(let_type(a), let_type(b)) && apply(let_value(a), let_value(b)) && apply(let_body(a), let_body(b)); } lean_unreachable(); // LCOV_EXCL_LINE }
bool is_lt_no_level_params(expr const & a, expr const & b) { if (is_eqp(a, b)) return false; unsigned wa = get_weight(a); unsigned wb = get_weight(b); if (wa < wb) return true; if (wa > wb) return false; if (a.kind() != b.kind()) return a.kind() < b.kind(); switch (a.kind()) { case expr_kind::Var: return var_idx(a) < var_idx(b); case expr_kind::Constant: if (const_name(a) != const_name(b)) return const_name(a) < const_name(b); else return is_lt_no_level_params(const_levels(a), const_levels(b)); case expr_kind::App: if (is_lt_no_level_params(app_fn(a), app_fn(b))) return true; else if (is_lt_no_level_params(app_fn(b), app_fn(a))) return false; else return is_lt_no_level_params(app_arg(a), app_arg(b)); case expr_kind::Lambda: case expr_kind::Pi: if (is_lt_no_level_params(binding_domain(a), binding_domain(b))) return true; else if (is_lt_no_level_params(binding_domain(b), binding_domain(a))) return false; else return is_lt_no_level_params(binding_body(a), binding_body(b)); case expr_kind::Sort: return is_lt_no_level_params(sort_level(a), sort_level(b)); case expr_kind::Local: case expr_kind::Meta: if (mlocal_name(a) != mlocal_name(b)) return mlocal_name(a) < mlocal_name(b); else return is_lt_no_level_params(mlocal_type(a), mlocal_type(b)); case expr_kind::Macro: if (macro_def(a) != macro_def(b)) return macro_def(a) < macro_def(b); if (macro_num_args(a) != macro_num_args(b)) return macro_num_args(a) < macro_num_args(b); for (unsigned i = 0; i < macro_num_args(a); i++) { if (is_lt_no_level_params(macro_arg(a, i), macro_arg(b, i))) return true; else if (is_lt_no_level_params(macro_arg(b, i), macro_arg(a, i))) return false; } return false; } lean_unreachable(); }
void PrescribedMoleFractionsDirichletOldStyleBCFactory:: convert_mole_fracs_and_add_to_func (const GetPot& input, const std::vector<libMesh::Number>& species_mole_fracs, const SpeciesMassFractionsVariable& species_fe_var, libMesh::CompositeFunction<libMesh::Number>& composite_func) const { const std::string& material = species_fe_var.material(); /*! \todo We should have a ChemsitryWarehouse or something to just grab this from one place instead of rebuilding. */ ChemistryBuilder chem_builder; std::unique_ptr<ChemistryType> chem_ptr; chem_builder.build_chemistry(input,material,chem_ptr); const ChemistryType & chem = *chem_ptr; const unsigned int n_vars = species_mole_fracs.size(); // Compute M libMesh::Real M = 0.0; for( unsigned int s = 0; s < n_vars; s++ ) M += species_mole_fracs[s]*chem.M(s); // Convert mole fractions to mass fractions and add to function for( unsigned int s = 0; s < n_vars; s++ ) { libMesh::Number species_mass_fracs =species_mole_fracs[s]*chem.M(s)/M; std::vector<VariableIndex> var_idx(1,species_fe_var.species(s)); libMesh::ConstFunction<libMesh::Number> const_func(species_mass_fracs); composite_func.attach_subfunction(const_func,var_idx); } }
void DisplacementContinuationSolver::increment_displacement( GRINS::MultiphysicsSystem& system, libMesh::EquationSystems& equation_system, const libMesh::Real displacement ) { // Get DirichetBoundaries vector. libMesh::DirichletBoundaries* d_vector = system.get_dof_map().get_dirichlet_boundaries(); // Get the DirichletBoundary we want libMesh::DirichletBoundary* dirichlet = (*d_vector)[_bc_index]; // Kill the old FunctionBase object and put in our new one. libMesh::FunctionBase<libMesh::Real>* composite_func_ptr = new libMesh::CompositeFunction<libMesh::Real>; libMesh::CompositeFunction<libMesh::Real>& composite_func = libMesh::cast_ref<libMesh::CompositeFunction<libMesh::Real>&>( *composite_func_ptr ); std::vector<VariableIndex> var_idx(1,0); // Hardcoding to Ux displacement component composite_func.attach_subfunction( libMesh::ConstFunction<libMesh::Real>(displacement), var_idx ); // DirichletBoundary now takes ownership of the pointer dirichlet->f.reset(composite_func_ptr); // Need to reinit system equation_system.reinit(); return; }
expr copy(expr const & a) { switch (a.kind()) { case expr_kind::Var: return mk_var(var_idx(a)); case expr_kind::Constant: return mk_constant(const_name(a)); case expr_kind::Type: return mk_type(ty_level(a)); case expr_kind::Value: return mk_value(static_cast<expr_value*>(a.raw())->m_val); case expr_kind::App: return mk_app(num_args(a), begin_args(a)); case expr_kind::Eq: return mk_eq(eq_lhs(a), eq_rhs(a)); case expr_kind::Lambda: return mk_lambda(abst_name(a), abst_domain(a), abst_body(a)); case expr_kind::Pi: return mk_pi(abst_name(a), abst_domain(a), abst_body(a)); case expr_kind::Let: return mk_let(let_name(a), let_type(a), let_value(a), let_body(a)); case expr_kind::MetaVar: return mk_metavar(metavar_idx(a), metavar_ctx(a)); } lean_unreachable(); }
/** \brief Given \c a, an expression that is the denotation of an expression, if \c a is a variable, then use the actions in the transitions \c ts to expand \c a. The idea is to produce a head symbol we can use to decide whether the notation should be considered during pretty printing. \see get_head_index */ static expr expand_pp_pattern(unsigned num, transition const * ts, expr const & a) { lean_assert(is_simple(num, ts)); if (!is_var(a)) return a; return replace(a, [&](expr const & e) { if (is_var(e)) { unsigned vidx = var_idx(e); unsigned i = num; unsigned offset = 0; while (i > 0) { --i; action const & act = ts[i].get_action(); switch (act.kind()) { case action_kind::Binder: case action_kind::Binders: case action_kind::Skip: break; case action_kind::Ext: case action_kind::LuaExt: lean_unreachable(); case action_kind::Expr: if (vidx == 0) return none_expr(); offset++; vidx--; break; case action_kind::Exprs: if (vidx == 0) return some_expr(lift_free_vars(act.get_rec(), offset)); offset++; vidx--; break; case action_kind::ScopedExpr: if (vidx == 0) return some_expr(lift_free_vars(act.get_rec(), offset)); offset++; vidx--; break; } } return none_expr(); } else { return none_expr(); } }); }
void ConstantFunctionDirichletBCFactory::add_found_vars( const GetPot& input, MultiphysicsSystem& system, const std::string& section, const std::set<std::string>& vars_found, libMesh::CompositeFunction<libMesh::Number>& composite_func, std::set<std::string>& vars_added ) const { libMesh::Number invalid_num = std::numeric_limits<libMesh::Number>::max(); for( std::set<std::string>::const_iterator var = vars_found.begin(); var != vars_found.end(); ++var ) { std::vector<VariableIndex> var_idx(1,system.variable_number(*var)); libMesh::Number value = input(section+"/"+(*var),invalid_num); libMesh::ConstFunction<libMesh::Number> const_func(value); composite_func.attach_subfunction(const_func,var_idx); } vars_added = vars_found; }
/* Return true iff v is of the form (g y_1 ... y_n) where y_i is a constant or a variable. Moreover, y_i's variables are pairwise distinct. */ bool is_simple_application(expr const & v) { buffer<expr> ys; buffer<bool> bitmap; expr const & g = get_app_args(v, ys); if (!is_constant(g) && !is_var(g)) return false; for (expr const & y : ys) { if (!is_var(y) && !is_constant(y)) return false; if (is_var(y)) { unsigned vidx = var_idx(y); if (vidx >= bitmap.size()) bitmap.resize(vidx+1, false); if (bitmap[vidx]) { /* y_i's are not pairwise distinct */ return false; } bitmap[vidx] = true; } } return true; }
static bool is_permutation(expr const & lhs, expr const & rhs, unsigned offset, buffer<optional<unsigned>> & p) { if (lhs.kind() != rhs.kind()) return false; switch (lhs.kind()) { case expr_kind::Constant: case expr_kind::Sort: case expr_kind::Meta: case expr_kind::Local: return lhs == rhs; case expr_kind::Var: if (var_idx(lhs) < offset) { return lhs == rhs; // locally bound variable } else if (var_idx(lhs) - offset < p.size()) { if (p[var_idx(lhs) - offset]) { return *(p[var_idx(lhs) - offset]) == var_idx(rhs); } else { p[var_idx(lhs) - offset] = var_idx(rhs); return true; } } else { return lhs == rhs; // free variable } case expr_kind::Lambda: case expr_kind::Pi: return is_permutation(binding_domain(lhs), binding_domain(rhs), offset, p) && is_permutation(binding_body(lhs), binding_body(rhs), offset+1, p); case expr_kind::App: return is_permutation(app_fn(lhs), app_fn(rhs), offset, p) && is_permutation(app_arg(lhs), app_arg(rhs), offset, p); case expr_kind::Macro: if (macro_def(lhs) != macro_def(rhs) || macro_num_args(lhs) != macro_num_args(rhs)) return false; for (unsigned i = 0; i < macro_num_args(lhs); i++) { if (!is_permutation(macro_arg(lhs, i), macro_arg(rhs, i), offset, p)) return false; } return true; } lean_unreachable(); }
bool light_lt_manager::is_lt(expr const & a, expr const & b) { if (is_eqp(a, b)) return false; unsigned wa = get_weight(a); unsigned wb = get_weight(b); if (wa < wb) return true; if (wa > wb) return false; if (is_constant(get_app_fn(a))) { unsigned const * light_arg = m_lrs.find(const_name(get_app_fn(a))); if (light_arg) { buffer<expr> args; get_app_args(a, args); if (args.size() > *light_arg) return is_lt(args[*light_arg], b); } } if (is_constant(get_app_fn(b))) { unsigned const * light_arg = m_lrs.find(const_name(get_app_fn(b))); if (light_arg) { buffer<expr> args; get_app_args(b, args); if (args.size() > *light_arg) return !is_lt(args[*light_arg], a); } } if (a.kind() != b.kind()) return a.kind() < b.kind(); if (a == b) return false; switch (a.kind()) { case expr_kind::Var: return var_idx(a) < var_idx(b); case expr_kind::Constant: if (const_name(a) != const_name(b)) return const_name(a) < const_name(b); else return ::lean::is_lt(const_levels(a), const_levels(b), false); case expr_kind::App: if (app_fn(a) != app_fn(b)) return is_lt(app_fn(a), app_fn(b)); else return is_lt(app_arg(a), app_arg(b)); case expr_kind::Lambda: case expr_kind::Pi: if (binding_domain(a) != binding_domain(b)) return is_lt(binding_domain(a), binding_domain(b)); else return is_lt(binding_body(a), binding_body(b)); case expr_kind::Sort: return ::lean::is_lt(sort_level(a), sort_level(b), false); case expr_kind::Local: case expr_kind::Meta: if (mlocal_name(a) != mlocal_name(b)) return mlocal_name(a) < mlocal_name(b); else return is_lt(mlocal_type(a), mlocal_type(b)); case expr_kind::Macro: if (macro_def(a) != macro_def(b)) return macro_def(a) < macro_def(b); if (macro_num_args(a) != macro_num_args(b)) return macro_num_args(a) < macro_num_args(b); for (unsigned i = 0; i < macro_num_args(a); i++) { if (macro_arg(a, i) != macro_arg(b, i)) return is_lt(macro_arg(a, i), macro_arg(b, i)); } return false; } lean_unreachable(); // LCOV_EXCL_LINE }
bool abstract_expr_manager::is_equal(expr const & a, expr const & b) { if (is_eqp(a, b)) return true; if (a.kind() != b.kind()) return false; if (is_var(a)) return var_idx(a) == var_idx(b); bool is_eq; switch (a.kind()) { case expr_kind::Var: lean_unreachable(); // LCOV_EXCL_LINE case expr_kind::Constant: case expr_kind::Sort: return a == b; case expr_kind::Meta: case expr_kind::Local: return mlocal_name(a) == mlocal_name(b) && is_equal(mlocal_type(a), mlocal_type(b)); case expr_kind::Lambda: case expr_kind::Pi: if (!is_equal(binding_domain(a), binding_domain(b))) return false; // see comment at abstract_expr_manager::hash m_locals.push_back(instantiate_rev(m_tctx.mk_tmp_local(binding_domain(a)), m_locals.size(), m_locals.data())); is_eq = is_equal(binding_body(a), binding_body(b)); m_locals.pop_back(); return is_eq; case expr_kind::Macro: if (macro_def(a) != macro_def(b) || macro_num_args(a) != macro_num_args(b)) return false; for (unsigned i = 0; i < macro_num_args(a); i++) { if (!is_equal(macro_arg(a, i), macro_arg(b, i))) return false; } return true; case expr_kind::App: buffer<expr> a_args, b_args; expr const & f_a = get_app_args(a, a_args); expr const & f_b = get_app_args(b, b_args); if (!is_equal(f_a, f_b)) return false; if (a_args.size() != b_args.size()) return false; unsigned prefix_sz = m_congr_lemma_manager.get_specialization_prefix_size(instantiate_rev(f_a, m_locals.size(), m_locals.data()), a_args.size()); for (unsigned i = 0; i < prefix_sz; i++) { if (!is_equal(a_args[i], b_args[i])) return false; } expr new_f_a = a; unsigned rest_sz = a_args.size() - prefix_sz; for (unsigned i = 0; i < rest_sz; i++) { new_f_a = app_fn(new_f_a); } new_f_a = instantiate_rev(new_f_a, m_locals.size(), m_locals.data()); optional<congr_lemma> congr = m_congr_lemma_manager.mk_congr(new_f_a, rest_sz); bool not_equal = false; if (!congr) { for (unsigned i = prefix_sz; i < a_args.size(); ++i) { if (!is_equal(a_args[i], b_args[i])) { not_equal = true; break; } } } else { lean_assert(length(congr->get_arg_kinds()) == rest_sz); unsigned i = prefix_sz; for_each(congr->get_arg_kinds(), [&](congr_arg_kind const & c_kind) { if (not_equal) return; if (c_kind != congr_arg_kind::Cast && !is_equal(a_args[i], b_args[i])) { not_equal = true; } i++; }); } return !not_equal; } lean_unreachable(); // LCOV_EXCL_LINE }
bool is_lt(expr const & a, expr const & b, bool use_hash) { if (is_eqp(a, b)) return false; unsigned da = get_depth(a); unsigned db = get_depth(b); if (da < db) return true; if (da > db) return false; if (a.kind() != b.kind()) return a.kind() < b.kind(); if (use_hash) { if (a.hash() < b.hash()) return true; if (a.hash() > b.hash()) return false; } if (a == b) return false; if (is_var(a)) return var_idx(a) < var_idx(b); switch (a.kind()) { case expr_kind::Var: lean_unreachable(); // LCOV_EXCL_LINE case expr_kind::Constant: return const_name(a) < const_name(b); case expr_kind::App: if (num_args(a) != num_args(b)) return num_args(a) < num_args(b); for (unsigned i = 0; i < num_args(a); i++) { if (arg(a, i) != arg(b, i)) return is_lt(arg(a, i), arg(b, i), use_hash); } lean_unreachable(); // LCOV_EXCL_LINE case expr_kind::Lambda: // Remark: we ignore get_abs_name because we want alpha-equivalence case expr_kind::Pi: if (abst_domain(a) != abst_domain(b)) return is_lt(abst_domain(a), abst_domain(b), use_hash); else return is_lt(abst_body(a), abst_body(b), use_hash); case expr_kind::Type: return ty_level(a) < ty_level(b); case expr_kind::Value: return to_value(a) < to_value(b); case expr_kind::Let: if (let_type(a) != let_type(b)) { return is_lt(let_type(a), let_type(b), use_hash); } else if (let_value(a) != let_value(b)){ return is_lt(let_value(a), let_value(b), use_hash); } else { return is_lt(let_body(a), let_body(b), use_hash); } case expr_kind::MetaVar: if (metavar_name(a) != metavar_name(b)) { return metavar_name(a) < metavar_name(b); } else { auto it1 = metavar_lctx(a).begin(); auto it2 = metavar_lctx(b).begin(); auto end1 = metavar_lctx(a).end(); auto end2 = metavar_lctx(b).end(); for (; it1 != end1 && it2 != end2; ++it1, ++it2) { if (it1->kind() != it2->kind()) { return it1->kind() < it2->kind(); } else if (it1->s() != it2->s()) { return it1->s() < it2->s(); } else if (it1->is_inst()) { if (it1->v() != it2->v()) return is_lt(it1->v(), it2->v(), use_hash); } else { if (it1->n() != it2->n()) return it1->n() < it2->n(); } } return it1 == end1 && it2 != end2; } } lean_unreachable(); // LCOV_EXCL_LINE }
void MoleFractionsDirichletBCFactory::add_mole_frac_to_mass_frac(const GetPot& input, const std::string& section, const std::set<std::string>& vars_found, const std::string& material, const SpeciesMassFractionsVariable& species_fe_var, libMesh::CompositeFunction<libMesh::Number>& composite_func, std::set<std::string>& vars_added) const { unsigned int n_vars_found = vars_found.size(); // Parse in all the species mole fracs that are in the input (it is assumed non-specified are 0) std::vector<libMesh::Number> species_mole_fracs(n_vars_found); libMesh::Number invalid_num = std::numeric_limits<libMesh::Number>::max(); { unsigned int count = 0; for(std::set<std::string>::const_iterator var = vars_found.begin(); var != vars_found.end(); ++var ) { species_mole_fracs[count] = input(section+"/"+(*var),invalid_num); count++; } } // Make sure mole fracs sum to 1 libMesh::Number sum = 0.0; for(unsigned int v = 0; v < n_vars_found; v++ ) sum += species_mole_fracs[v]; libMesh::Number tol = std::numeric_limits<libMesh::Number>::epsilon()*10; if( std::abs(sum-1.0) > tol ) libmesh_error_msg("ERROR: Mole fractions do not sum to 1! Found sum = "+StringUtilities::T_to_string<libMesh::Number>(sum)); // Extract species names std::vector<std::string> species_names(n_vars_found); { unsigned int count = 0; for(std::set<std::string>::const_iterator var = vars_found.begin(); var != vars_found.end(); ++var ) { std::vector<std::string> split_name; // vars_found should have the form "X_<species name>" StringUtilities::split_string((*var),"_",split_name); libmesh_assert_equal_to(split_name[0],std::string("X")); libmesh_assert_equal_to(split_name.size(),2); species_names[count] = split_name[1]; count++; } } // Now convert to mass frac and add to composite function /*! \todo We should have a ChemsitryWarehouse or something to just grab this from one place instead of rebuilding. */ ChemistryType chem(input,material); libMesh::Real M = 0.0; for(unsigned int v = 0; v < n_vars_found; v++ ) { unsigned int s = chem.species_index(species_names[v]); M += species_mole_fracs[v]*chem.M(s); } const std::string& prefix = species_fe_var.prefix(); for(unsigned int v = 0; v < n_vars_found; v++ ) { // Finish computing species mass fraction unsigned int s = chem.species_index(species_names[v]); libMesh::Number species_mass_fracs = species_mole_fracs[v]*chem.M(s)/M; // Add the function std::vector<VariableIndex> var_idx(1,species_fe_var.species(s)); libMesh::ConstFunction<libMesh::Number> const_func(species_mass_fracs); composite_func.attach_subfunction(const_func,var_idx); // Log that we added this variable vars_added.insert(prefix+species_names[v]); } }