// Generated by rstantools.  Do not edit by hand.

/*
    cellvel is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    cellvel is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with cellvel.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MODELS_HPP
#define MODELS_HPP
#define STAN__SERVICES__COMMAND_HPP
#ifndef USE_STANC3
#define USE_STANC3
#endif
#include <rstan/rstaninc.hpp>
// Code generated by stanc v2.32.2
#include <stan/model/model_header.hpp>
namespace model_M_namespace {
using stan::model::model_base_crtp;
using namespace stan::math;
stan::math::profile_map profiles__;
static constexpr std::array<const char*, 80> locations_array__ =
  {" (found before start of program)",
  " (in 'M', line 28, column 2 to column 27)",
  " (in 'M', line 29, column 2 to column 28)",
  " (in 'M', line 31, column 2 to column 27)",
  " (in 'M', line 32, column 2 to column 28)",
  " (in 'M', line 34, column 2 to column 16)",
  " (in 'M', line 35, column 2 to column 29)",
  " (in 'M', line 37, column 2 to column 22)",
  " (in 'M', line 38, column 2 to column 29)",
  " (in 'M', line 39, column 2 to column 22)",
  " (in 'M', line 42, column 2 to column 34)",
  " (in 'M', line 43, column 2 to column 30)",
  " (in 'M', line 44, column 2 to column 26)",
  " (in 'M', line 45, column 2 to column 40)",
  " (in 'M', line 71, column 2 to column 29)",
  " (in 'M', line 72, column 2 to column 19)",
  " (in 'M', line 47, column 2 to column 56)",
  " (in 'M', line 52, column 6 to column 98)",
  " (in 'M', line 51, column 11 to line 53, column 5)",
  " (in 'M', line 50, column 6 to column 62)",
  " (in 'M', line 49, column 21 to line 51, column 5)",
  " (in 'M', line 49, column 4 to line 53, column 5)",
  " (in 'M', line 48, column 21 to line 54, column 3)",
  " (in 'M', line 48, column 2 to line 54, column 3)",
  " (in 'M', line 55, column 2 to column 20)",
  " (in 'M', line 56, column 2 to column 44)",
  " (in 'M', line 73, column 2 to column 47)",
  " (in 'M', line 75, column 4 to column 91)",
  " (in 'M', line 74, column 16 to line 76, column 3)",
  " (in 'M', line 74, column 2 to line 76, column 3)",
  " (in 'M', line 59, column 2 to column 54)",
  " (in 'M', line 60, column 2 to column 57)",
  " (in 'M', line 61, column 2 to column 60)",
  " (in 'M', line 62, column 2 to column 62)",
  " (in 'M', line 63, column 2 to column 57)",
  " (in 'M', line 64, column 2 to column 66)",
  " (in 'M', line 65, column 2 to column 21)",
  " (in 'M', line 66, column 2 to column 21)",
  " (in 'M', line 67, column 2 to column 21)",
  " (in 'M', line 68, column 2 to column 59)",
  " (in 'M', line 2, column 2 to column 17)",
  " (in 'M', line 3, column 2 to column 22)",
  " (in 'M', line 4, column 2 to column 23)",
  " (in 'M', line 5, column 2 to column 29)",
  " (in 'M', line 6, column 2 to column 23)",
  " (in 'M', line 7, column 9 to column 10)",
  " (in 'M', line 7, column 2 to column 14)",
  " (in 'M', line 8, column 15 to column 16)",
  " (in 'M', line 8, column 2 to column 18)",
  " (in 'M', line 9, column 16 to column 22)",
  " (in 'M', line 9, column 2 to column 24)",
  " (in 'M', line 10, column 22 to column 28)",
  " (in 'M', line 10, column 2 to column 30)",
  " (in 'M', line 11, column 16 to column 29)",
  " (in 'M', line 11, column 2 to column 31)",
  " (in 'M', line 12, column 14 to column 20)",
  " (in 'M', line 12, column 2 to column 22)",
  " (in 'M', line 14, column 2 to column 23)",
  " (in 'M', line 15, column 2 to column 24)",
  " (in 'M', line 16, column 2 to column 25)",
  " (in 'M', line 17, column 2 to column 26)",
  " (in 'M', line 18, column 2 to column 26)",
  " (in 'M', line 19, column 2 to column 27)",
  " (in 'M', line 20, column 2 to column 24)",
  " (in 'M', line 21, column 2 to column 25)",
  " (in 'M', line 22, column 2 to column 27)",
  " (in 'M', line 23, column 2 to column 28)",
  " (in 'M', line 24, column 2 to column 24)",
  " (in 'M', line 25, column 2 to column 25)",
  " (in 'M', line 28, column 10 to column 17)",
  " (in 'M', line 29, column 10 to column 17)",
  " (in 'M', line 37, column 10 to column 16)",
  " (in 'M', line 38, column 10 to column 23)",
  " (in 'M', line 39, column 10 to column 16)",
  " (in 'M', line 42, column 20 to column 26)",
  " (in 'M', line 43, column 19 to column 25)",
  " (in 'M', line 44, column 10 to column 16)",
  " (in 'M', line 45, column 10 to column 23)",
  " (in 'M', line 71, column 21 to column 27)",
  " (in 'M', line 72, column 16 to column 17)"};
#include <stan_meta_header.hpp>
class model_M final : public model_base_crtp<model_M> {
private:
  int N;
  int N_well;
  int N_plate;
  int N_plate_group;
  int N_group;
  Eigen::Matrix<double,-1,1> y_data__;
  std::vector<int> well_id;
  std::vector<int> plate_id;
  std::vector<int> plate_group_id;
  std::vector<int> group_id;
  std::vector<int> offset;
  double prior_alpha_p_M;
  double prior_alpha_p_SD;
  double prior_sigma_bio_M;
  double prior_sigma_bio_SD;
  double prior_sigma_tech_M;
  double prior_sigma_tech_SD;
  double prior_kappa_mu_M;
  double prior_kappa_mu_SD;
  double prior_kappa_sigma_M;
  double prior_kappa_sigma_SD;
  double prior_mu_group_M;
  double prior_mu_group_SD;
  Eigen::Map<Eigen::Matrix<double,-1,1>> y{nullptr, 0};
public:
  ~model_M() {}
  model_M(stan::io::var_context& context__, unsigned int random_seed__ = 0,
          std::ostream* pstream__ = nullptr) : model_base_crtp(0) {
    int current_statement__ = 0;
    using local_scalar_t__ = double;
    boost::ecuyer1988 base_rng__ =
      stan::services::util::create_rng(random_seed__, 0);
    // suppress unused var warning
    (void) base_rng__;
    static constexpr const char* function__ = "model_M_namespace::model_M";
    // suppress unused var warning
    (void) function__;
    local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
    // suppress unused var warning
    (void) DUMMY_VAR__;
    try {
      int pos__ = std::numeric_limits<int>::min();
      pos__ = 1;
      current_statement__ = 40;
      context__.validate_dims("data initialization", "N", "int",
        std::vector<size_t>{});
      N = std::numeric_limits<int>::min();
      current_statement__ = 40;
      N = context__.vals_i("N")[(1 - 1)];
      current_statement__ = 40;
      stan::math::check_greater_or_equal(function__, "N", N, 0);
      current_statement__ = 41;
      context__.validate_dims("data initialization", "N_well", "int",
        std::vector<size_t>{});
      N_well = std::numeric_limits<int>::min();
      current_statement__ = 41;
      N_well = context__.vals_i("N_well")[(1 - 1)];
      current_statement__ = 41;
      stan::math::check_greater_or_equal(function__, "N_well", N_well, 0);
      current_statement__ = 42;
      context__.validate_dims("data initialization", "N_plate", "int",
        std::vector<size_t>{});
      N_plate = std::numeric_limits<int>::min();
      current_statement__ = 42;
      N_plate = context__.vals_i("N_plate")[(1 - 1)];
      current_statement__ = 42;
      stan::math::check_greater_or_equal(function__, "N_plate", N_plate, 0);
      current_statement__ = 43;
      context__.validate_dims("data initialization", "N_plate_group", "int",
        std::vector<size_t>{});
      N_plate_group = std::numeric_limits<int>::min();
      current_statement__ = 43;
      N_plate_group = context__.vals_i("N_plate_group")[(1 - 1)];
      current_statement__ = 43;
      stan::math::check_greater_or_equal(function__, "N_plate_group",
        N_plate_group, 0);
      current_statement__ = 44;
      context__.validate_dims("data initialization", "N_group", "int",
        std::vector<size_t>{});
      N_group = std::numeric_limits<int>::min();
      current_statement__ = 44;
      N_group = context__.vals_i("N_group")[(1 - 1)];
      current_statement__ = 44;
      stan::math::check_greater_or_equal(function__, "N_group", N_group, 0);
      current_statement__ = 45;
      stan::math::validate_non_negative_index("y", "N", N);
      current_statement__ = 46;
      context__.validate_dims("data initialization", "y", "double",
        std::vector<size_t>{static_cast<size_t>(N)});
      y_data__ = Eigen::Matrix<double,-1,1>::Constant(N,
                   std::numeric_limits<double>::quiet_NaN());
      new (&y) Eigen::Map<Eigen::Matrix<double,-1,1>>(y_data__.data(), N);
      {
        std::vector<local_scalar_t__> y_flat__;
        current_statement__ = 46;
        y_flat__ = context__.vals_r("y");
        current_statement__ = 46;
        pos__ = 1;
        current_statement__ = 46;
        for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
          current_statement__ = 46;
          stan::model::assign(y, y_flat__[(pos__ - 1)],
            "assigning variable y", stan::model::index_uni(sym1__));
          current_statement__ = 46;
          pos__ = (pos__ + 1);
        }
      }
      current_statement__ = 47;
      stan::math::validate_non_negative_index("well_id", "N", N);
      current_statement__ = 48;
      context__.validate_dims("data initialization", "well_id", "int",
        std::vector<size_t>{static_cast<size_t>(N)});
      well_id = std::vector<int>(N, std::numeric_limits<int>::min());
      current_statement__ = 48;
      well_id = context__.vals_i("well_id");
      current_statement__ = 49;
      stan::math::validate_non_negative_index("plate_id", "N_well", N_well);
      current_statement__ = 50;
      context__.validate_dims("data initialization", "plate_id", "int",
        std::vector<size_t>{static_cast<size_t>(N_well)});
      plate_id = std::vector<int>(N_well, std::numeric_limits<int>::min());
      current_statement__ = 50;
      plate_id = context__.vals_i("plate_id");
      current_statement__ = 51;
      stan::math::validate_non_negative_index("plate_group_id", "N_well",
        N_well);
      current_statement__ = 52;
      context__.validate_dims("data initialization", "plate_group_id", "int",
        std::vector<size_t>{static_cast<size_t>(N_well)});
      plate_group_id = std::vector<int>(N_well,
                         std::numeric_limits<int>::min());
      current_statement__ = 52;
      plate_group_id = context__.vals_i("plate_group_id");
      current_statement__ = 53;
      stan::math::validate_non_negative_index("group_id", "N_plate_group",
        N_plate_group);
      current_statement__ = 54;
      context__.validate_dims("data initialization", "group_id", "int",
        std::vector<size_t>{static_cast<size_t>(N_plate_group)});
      group_id = std::vector<int>(N_plate_group,
                   std::numeric_limits<int>::min());
      current_statement__ = 54;
      group_id = context__.vals_i("group_id");
      current_statement__ = 55;
      stan::math::validate_non_negative_index("offset", "N_well", N_well);
      current_statement__ = 56;
      context__.validate_dims("data initialization", "offset", "int",
        std::vector<size_t>{static_cast<size_t>(N_well)});
      offset = std::vector<int>(N_well, std::numeric_limits<int>::min());
      current_statement__ = 56;
      offset = context__.vals_i("offset");
      current_statement__ = 57;
      context__.validate_dims("data initialization", "prior_alpha_p_M",
        "double", std::vector<size_t>{});
      prior_alpha_p_M = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 57;
      prior_alpha_p_M = context__.vals_r("prior_alpha_p_M")[(1 - 1)];
      current_statement__ = 58;
      context__.validate_dims("data initialization", "prior_alpha_p_SD",
        "double", std::vector<size_t>{});
      prior_alpha_p_SD = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 58;
      prior_alpha_p_SD = context__.vals_r("prior_alpha_p_SD")[(1 - 1)];
      current_statement__ = 59;
      context__.validate_dims("data initialization", "prior_sigma_bio_M",
        "double", std::vector<size_t>{});
      prior_sigma_bio_M = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 59;
      prior_sigma_bio_M = context__.vals_r("prior_sigma_bio_M")[(1 - 1)];
      current_statement__ = 60;
      context__.validate_dims("data initialization", "prior_sigma_bio_SD",
        "double", std::vector<size_t>{});
      prior_sigma_bio_SD = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 60;
      prior_sigma_bio_SD = context__.vals_r("prior_sigma_bio_SD")[(1 - 1)];
      current_statement__ = 61;
      context__.validate_dims("data initialization", "prior_sigma_tech_M",
        "double", std::vector<size_t>{});
      prior_sigma_tech_M = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 61;
      prior_sigma_tech_M = context__.vals_r("prior_sigma_tech_M")[(1 - 1)];
      current_statement__ = 62;
      context__.validate_dims("data initialization", "prior_sigma_tech_SD",
        "double", std::vector<size_t>{});
      prior_sigma_tech_SD = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 62;
      prior_sigma_tech_SD = context__.vals_r("prior_sigma_tech_SD")[(1 - 1)];
      current_statement__ = 63;
      context__.validate_dims("data initialization", "prior_kappa_mu_M",
        "double", std::vector<size_t>{});
      prior_kappa_mu_M = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 63;
      prior_kappa_mu_M = context__.vals_r("prior_kappa_mu_M")[(1 - 1)];
      current_statement__ = 64;
      context__.validate_dims("data initialization", "prior_kappa_mu_SD",
        "double", std::vector<size_t>{});
      prior_kappa_mu_SD = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 64;
      prior_kappa_mu_SD = context__.vals_r("prior_kappa_mu_SD")[(1 - 1)];
      current_statement__ = 65;
      context__.validate_dims("data initialization", "prior_kappa_sigma_M",
        "double", std::vector<size_t>{});
      prior_kappa_sigma_M = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 65;
      prior_kappa_sigma_M = context__.vals_r("prior_kappa_sigma_M")[(1 - 1)];
      current_statement__ = 66;
      context__.validate_dims("data initialization", "prior_kappa_sigma_SD",
        "double", std::vector<size_t>{});
      prior_kappa_sigma_SD = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 66;
      prior_kappa_sigma_SD = context__.vals_r("prior_kappa_sigma_SD")[(1 -
        1)];
      current_statement__ = 67;
      context__.validate_dims("data initialization", "prior_mu_group_M",
        "double", std::vector<size_t>{});
      prior_mu_group_M = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 67;
      prior_mu_group_M = context__.vals_r("prior_mu_group_M")[(1 - 1)];
      current_statement__ = 68;
      context__.validate_dims("data initialization", "prior_mu_group_SD",
        "double", std::vector<size_t>{});
      prior_mu_group_SD = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 68;
      prior_mu_group_SD = context__.vals_r("prior_mu_group_SD")[(1 - 1)];
      current_statement__ = 69;
      stan::math::validate_non_negative_index("alpha_p", "N_plate", N_plate);
      current_statement__ = 70;
      stan::math::validate_non_negative_index("mu_group", "N_group", N_group);
      current_statement__ = 71;
      stan::math::validate_non_negative_index("z_1", "N_well", N_well);
      current_statement__ = 72;
      stan::math::validate_non_negative_index("z_2", "N_plate_group",
        N_plate_group);
      current_statement__ = 73;
      stan::math::validate_non_negative_index("z_3", "N_well", N_well);
      current_statement__ = 74;
      stan::math::validate_non_negative_index("kappa", "N_well", N_well);
      current_statement__ = 75;
      stan::math::validate_non_negative_index("mu", "N_well", N_well);
      current_statement__ = 76;
      stan::math::validate_non_negative_index("mu_well", "N_well", N_well);
      current_statement__ = 77;
      stan::math::validate_non_negative_index("mu_plate_group",
        "N_plate_group", N_plate_group);
      current_statement__ = 78;
      stan::math::validate_non_negative_index("y_hat_sample", "N_well",
        N_well);
      current_statement__ = 79;
      stan::math::validate_non_negative_index("log_lik", "N", N);
    } catch (const std::exception& e) {
      stan::lang::rethrow_located(e, locations_array__[current_statement__]);
    }
    num_params_r__ = N_plate + N_group + 1 + 1 + 1 + 1 + N_well +
      N_plate_group + N_well;
  }
  inline std::string model_name() const final {
    return "model_M";
  }
  inline std::vector<std::string> model_compile_info() const noexcept {
    return std::vector<std::string>{"stanc_version = stanc3 v2.32.2",
             "stancflags = --allow-undefined"};
  }
  template <bool propto__, bool jacobian__, typename VecR, typename VecI,
            stan::require_vector_like_t<VecR>* = nullptr,
            stan::require_vector_like_vt<std::is_integral, VecI>* = nullptr>
  inline stan::scalar_type_t<VecR>
  log_prob_impl(VecR& params_r__, VecI& params_i__, std::ostream*
                pstream__ = nullptr) const {
    using T__ = stan::scalar_type_t<VecR>;
    using local_scalar_t__ = T__;
    T__ lp__(0.0);
    stan::math::accumulator<T__> lp_accum__;
    stan::io::deserializer<local_scalar_t__> in__(params_r__, params_i__);
    int current_statement__ = 0;
    local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
    // suppress unused var warning
    (void) DUMMY_VAR__;
    static constexpr const char* function__ = "model_M_namespace::log_prob";
    // suppress unused var warning
    (void) function__;
    try {
      Eigen::Matrix<local_scalar_t__,-1,1> alpha_p =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_plate, DUMMY_VAR__);
      current_statement__ = 1;
      alpha_p = in__.template read<
                  Eigen::Matrix<local_scalar_t__,-1,1>>(N_plate);
      Eigen::Matrix<local_scalar_t__,-1,1> mu_group =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_group, DUMMY_VAR__);
      current_statement__ = 2;
      mu_group = in__.template read<
                   Eigen::Matrix<local_scalar_t__,-1,1>>(N_group);
      local_scalar_t__ sigma_bio = DUMMY_VAR__;
      current_statement__ = 3;
      sigma_bio = in__.template read_constrain_lb<local_scalar_t__,
                    jacobian__>(0, lp__);
      local_scalar_t__ sigma_tech = DUMMY_VAR__;
      current_statement__ = 4;
      sigma_tech = in__.template read_constrain_lb<local_scalar_t__,
                     jacobian__>(0, lp__);
      local_scalar_t__ kappa_mu = DUMMY_VAR__;
      current_statement__ = 5;
      kappa_mu = in__.template read<local_scalar_t__>();
      local_scalar_t__ kappa_sigma = DUMMY_VAR__;
      current_statement__ = 6;
      kappa_sigma = in__.template read_constrain_lb<local_scalar_t__,
                      jacobian__>(0, lp__);
      Eigen::Matrix<local_scalar_t__,-1,1> z_1 =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_well, DUMMY_VAR__);
      current_statement__ = 7;
      z_1 = in__.template read<Eigen::Matrix<local_scalar_t__,-1,1>>(N_well);
      Eigen::Matrix<local_scalar_t__,-1,1> z_2 =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_plate_group,
          DUMMY_VAR__);
      current_statement__ = 8;
      z_2 = in__.template read<
              Eigen::Matrix<local_scalar_t__,-1,1>>(N_plate_group);
      Eigen::Matrix<local_scalar_t__,-1,1> z_3 =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_well, DUMMY_VAR__);
      current_statement__ = 9;
      z_3 = in__.template read<Eigen::Matrix<local_scalar_t__,-1,1>>(N_well);
      Eigen::Matrix<local_scalar_t__,-1,1> kappa =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_well, DUMMY_VAR__);
      Eigen::Matrix<local_scalar_t__,-1,1> mu =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_well, DUMMY_VAR__);
      Eigen::Matrix<local_scalar_t__,-1,1> mu_well =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_well, DUMMY_VAR__);
      Eigen::Matrix<local_scalar_t__,-1,1> mu_plate_group =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_plate_group,
          DUMMY_VAR__);
      current_statement__ = 16;
      stan::model::assign(mu_plate_group,
        stan::math::add(
          stan::model::rvalue(mu_group, "mu_group",
            stan::model::index_multi(group_id)),
          stan::math::multiply(sigma_bio, z_2)),
        "assigning variable mu_plate_group");
      current_statement__ = 23;
      for (int w = 1; w <= N_well; ++w) {
        current_statement__ = 21;
        if (stan::math::logical_eq(
              stan::model::rvalue(offset, "offset", stan::model::index_uni(w)),
              1)) {
          current_statement__ = 19;
          stan::model::assign(mu_well,
            (stan::model::rvalue(alpha_p, "alpha_p",
               stan::model::index_uni(
                 stan::model::rvalue(plate_id, "plate_id",
                   stan::model::index_uni(w)))) + (sigma_tech *
            stan::model::rvalue(z_1, "z_1", stan::model::index_uni(w)))),
            "assigning variable mu_well", stan::model::index_uni(w));
        } else {
          current_statement__ = 17;
          stan::model::assign(mu_well,
            ((stan::model::rvalue(alpha_p, "alpha_p",
                stan::model::index_uni(
                  stan::model::rvalue(plate_id, "plate_id",
                    stan::model::index_uni(w)))) +
            stan::model::rvalue(mu_plate_group, "mu_plate_group",
              stan::model::index_uni(
                stan::model::rvalue(plate_group_id, "plate_group_id",
                  stan::model::index_uni(w))))) + (sigma_tech *
            stan::model::rvalue(z_1, "z_1", stan::model::index_uni(w)))),
            "assigning variable mu_well", stan::model::index_uni(w));
        }
      }
      current_statement__ = 24;
      stan::model::assign(mu, stan::math::exp(mu_well),
        "assigning variable mu");
      current_statement__ = 25;
      stan::model::assign(kappa,
        stan::math::exp(
          stan::math::add(kappa_mu, stan::math::multiply(kappa_sigma, z_3))),
        "assigning variable kappa");
      current_statement__ = 10;
      stan::math::check_greater_or_equal(function__, "kappa", kappa, 0);
      current_statement__ = 11;
      stan::math::check_greater_or_equal(function__, "mu", mu, 0);
      {
        current_statement__ = 30;
        lp_accum__.add(stan::math::normal_lpdf<propto__>(alpha_p,
                         prior_alpha_p_M, prior_alpha_p_SD));
        current_statement__ = 31;
        lp_accum__.add(stan::math::normal_lpdf<propto__>(mu_group,
                         prior_mu_group_M, prior_mu_group_SD));
        current_statement__ = 32;
        lp_accum__.add(stan::math::normal_lpdf<propto__>(sigma_bio,
                         prior_sigma_bio_M, prior_sigma_bio_SD));
        current_statement__ = 33;
        lp_accum__.add(stan::math::normal_lpdf<propto__>(sigma_tech,
                         prior_sigma_tech_M, prior_sigma_bio_SD));
        current_statement__ = 34;
        lp_accum__.add(stan::math::normal_lpdf<propto__>(kappa_mu,
                         prior_kappa_mu_M, prior_kappa_mu_SD));
        current_statement__ = 35;
        lp_accum__.add(stan::math::normal_lpdf<propto__>(kappa_sigma,
                         prior_kappa_sigma_M, prior_kappa_sigma_SD));
        current_statement__ = 36;
        lp_accum__.add(stan::math::std_normal_lpdf<propto__>(z_1));
        current_statement__ = 37;
        lp_accum__.add(stan::math::std_normal_lpdf<propto__>(z_2));
        current_statement__ = 38;
        lp_accum__.add(stan::math::std_normal_lpdf<propto__>(z_3));
        current_statement__ = 39;
        lp_accum__.add(stan::math::gamma_lpdf<propto__>(y,
                         stan::model::rvalue(kappa, "kappa",
                           stan::model::index_multi(well_id)),
                         stan::math::elt_divide(
                           stan::model::rvalue(kappa, "kappa",
                             stan::model::index_multi(well_id)),
                           stan::model::rvalue(mu, "mu",
                             stan::model::index_multi(well_id)))));
      }
    } catch (const std::exception& e) {
      stan::lang::rethrow_located(e, locations_array__[current_statement__]);
    }
    lp_accum__.add(lp__);
    return lp_accum__.sum();
  }
  template <typename RNG, typename VecR, typename VecI, typename VecVar,
            stan::require_vector_like_vt<std::is_floating_point,
            VecR>* = nullptr, stan::require_vector_like_vt<std::is_integral,
            VecI>* = nullptr, stan::require_vector_vt<std::is_floating_point,
            VecVar>* = nullptr>
  inline void
  write_array_impl(RNG& base_rng__, VecR& params_r__, VecI& params_i__,
                   VecVar& vars__, const bool
                   emit_transformed_parameters__ = true, const bool
                   emit_generated_quantities__ = true, std::ostream*
                   pstream__ = nullptr) const {
    using local_scalar_t__ = double;
    stan::io::deserializer<local_scalar_t__> in__(params_r__, params_i__);
    stan::io::serializer<local_scalar_t__> out__(vars__);
    static constexpr bool propto__ = true;
    // suppress unused var warning
    (void) propto__;
    double lp__ = 0.0;
    // suppress unused var warning
    (void) lp__;
    int current_statement__ = 0;
    stan::math::accumulator<double> lp_accum__;
    local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
    // suppress unused var warning
    (void) DUMMY_VAR__;
    constexpr bool jacobian__ = false;
    static constexpr const char* function__ =
      "model_M_namespace::write_array";
    // suppress unused var warning
    (void) function__;
    try {
      Eigen::Matrix<double,-1,1> alpha_p =
        Eigen::Matrix<double,-1,1>::Constant(N_plate,
          std::numeric_limits<double>::quiet_NaN());
      current_statement__ = 1;
      alpha_p = in__.template read<
                  Eigen::Matrix<local_scalar_t__,-1,1>>(N_plate);
      Eigen::Matrix<double,-1,1> mu_group =
        Eigen::Matrix<double,-1,1>::Constant(N_group,
          std::numeric_limits<double>::quiet_NaN());
      current_statement__ = 2;
      mu_group = in__.template read<
                   Eigen::Matrix<local_scalar_t__,-1,1>>(N_group);
      double sigma_bio = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 3;
      sigma_bio = in__.template read_constrain_lb<local_scalar_t__,
                    jacobian__>(0, lp__);
      double sigma_tech = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 4;
      sigma_tech = in__.template read_constrain_lb<local_scalar_t__,
                     jacobian__>(0, lp__);
      double kappa_mu = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 5;
      kappa_mu = in__.template read<local_scalar_t__>();
      double kappa_sigma = std::numeric_limits<double>::quiet_NaN();
      current_statement__ = 6;
      kappa_sigma = in__.template read_constrain_lb<local_scalar_t__,
                      jacobian__>(0, lp__);
      Eigen::Matrix<double,-1,1> z_1 =
        Eigen::Matrix<double,-1,1>::Constant(N_well,
          std::numeric_limits<double>::quiet_NaN());
      current_statement__ = 7;
      z_1 = in__.template read<Eigen::Matrix<local_scalar_t__,-1,1>>(N_well);
      Eigen::Matrix<double,-1,1> z_2 =
        Eigen::Matrix<double,-1,1>::Constant(N_plate_group,
          std::numeric_limits<double>::quiet_NaN());
      current_statement__ = 8;
      z_2 = in__.template read<
              Eigen::Matrix<local_scalar_t__,-1,1>>(N_plate_group);
      Eigen::Matrix<double,-1,1> z_3 =
        Eigen::Matrix<double,-1,1>::Constant(N_well,
          std::numeric_limits<double>::quiet_NaN());
      current_statement__ = 9;
      z_3 = in__.template read<Eigen::Matrix<local_scalar_t__,-1,1>>(N_well);
      Eigen::Matrix<double,-1,1> kappa =
        Eigen::Matrix<double,-1,1>::Constant(N_well,
          std::numeric_limits<double>::quiet_NaN());
      Eigen::Matrix<double,-1,1> mu =
        Eigen::Matrix<double,-1,1>::Constant(N_well,
          std::numeric_limits<double>::quiet_NaN());
      Eigen::Matrix<double,-1,1> mu_well =
        Eigen::Matrix<double,-1,1>::Constant(N_well,
          std::numeric_limits<double>::quiet_NaN());
      Eigen::Matrix<double,-1,1> mu_plate_group =
        Eigen::Matrix<double,-1,1>::Constant(N_plate_group,
          std::numeric_limits<double>::quiet_NaN());
      out__.write(alpha_p);
      out__.write(mu_group);
      out__.write(sigma_bio);
      out__.write(sigma_tech);
      out__.write(kappa_mu);
      out__.write(kappa_sigma);
      out__.write(z_1);
      out__.write(z_2);
      out__.write(z_3);
      if (stan::math::logical_negation(
            (stan::math::primitive_value(emit_transformed_parameters__) ||
            stan::math::primitive_value(emit_generated_quantities__)))) {
        return ;
      }
      current_statement__ = 16;
      stan::model::assign(mu_plate_group,
        stan::math::add(
          stan::model::rvalue(mu_group, "mu_group",
            stan::model::index_multi(group_id)),
          stan::math::multiply(sigma_bio, z_2)),
        "assigning variable mu_plate_group");
      current_statement__ = 23;
      for (int w = 1; w <= N_well; ++w) {
        current_statement__ = 21;
        if (stan::math::logical_eq(
              stan::model::rvalue(offset, "offset", stan::model::index_uni(w)),
              1)) {
          current_statement__ = 19;
          stan::model::assign(mu_well,
            (stan::model::rvalue(alpha_p, "alpha_p",
               stan::model::index_uni(
                 stan::model::rvalue(plate_id, "plate_id",
                   stan::model::index_uni(w)))) + (sigma_tech *
            stan::model::rvalue(z_1, "z_1", stan::model::index_uni(w)))),
            "assigning variable mu_well", stan::model::index_uni(w));
        } else {
          current_statement__ = 17;
          stan::model::assign(mu_well,
            ((stan::model::rvalue(alpha_p, "alpha_p",
                stan::model::index_uni(
                  stan::model::rvalue(plate_id, "plate_id",
                    stan::model::index_uni(w)))) +
            stan::model::rvalue(mu_plate_group, "mu_plate_group",
              stan::model::index_uni(
                stan::model::rvalue(plate_group_id, "plate_group_id",
                  stan::model::index_uni(w))))) + (sigma_tech *
            stan::model::rvalue(z_1, "z_1", stan::model::index_uni(w)))),
            "assigning variable mu_well", stan::model::index_uni(w));
        }
      }
      current_statement__ = 24;
      stan::model::assign(mu, stan::math::exp(mu_well),
        "assigning variable mu");
      current_statement__ = 25;
      stan::model::assign(kappa,
        stan::math::exp(
          stan::math::add(kappa_mu, stan::math::multiply(kappa_sigma, z_3))),
        "assigning variable kappa");
      current_statement__ = 10;
      stan::math::check_greater_or_equal(function__, "kappa", kappa, 0);
      current_statement__ = 11;
      stan::math::check_greater_or_equal(function__, "mu", mu, 0);
      if (emit_transformed_parameters__) {
        out__.write(kappa);
        out__.write(mu);
        out__.write(mu_well);
        out__.write(mu_plate_group);
      }
      if (stan::math::logical_negation(emit_generated_quantities__)) {
        return ;
      }
      std::vector<double> y_hat_sample =
        std::vector<double>(N_well, std::numeric_limits<double>::quiet_NaN());
      std::vector<double> log_lik =
        std::vector<double>(N, std::numeric_limits<double>::quiet_NaN());
      current_statement__ = 26;
      stan::model::assign(y_hat_sample,
        stan::math::gamma_rng(kappa, stan::math::elt_divide(kappa, mu),
          base_rng__), "assigning variable y_hat_sample");
      current_statement__ = 29;
      for (int i = 1; i <= N; ++i) {
        current_statement__ = 27;
        stan::model::assign(log_lik,
          stan::math::gamma_lpdf<false>(
            stan::model::rvalue(y, "y", stan::model::index_uni(i)),
            stan::model::rvalue(kappa, "kappa",
              stan::model::index_uni(
                stan::model::rvalue(well_id, "well_id",
                  stan::model::index_uni(i)))),
            (stan::model::rvalue(kappa, "kappa",
               stan::model::index_uni(
                 stan::model::rvalue(well_id, "well_id",
                   stan::model::index_uni(i)))) /
            stan::model::rvalue(mu, "mu",
              stan::model::index_uni(
                stan::model::rvalue(well_id, "well_id",
                  stan::model::index_uni(i)))))),
          "assigning variable log_lik", stan::model::index_uni(i));
      }
      out__.write(y_hat_sample);
      out__.write(log_lik);
    } catch (const std::exception& e) {
      stan::lang::rethrow_located(e, locations_array__[current_statement__]);
    }
  }
  template <typename VecVar, typename VecI,
            stan::require_vector_t<VecVar>* = nullptr,
            stan::require_vector_like_vt<std::is_integral, VecI>* = nullptr>
  inline void
  unconstrain_array_impl(const VecVar& params_r__, const VecI& params_i__,
                         VecVar& vars__, std::ostream* pstream__ = nullptr) const {
    using local_scalar_t__ = double;
    stan::io::deserializer<local_scalar_t__> in__(params_r__, params_i__);
    stan::io::serializer<local_scalar_t__> out__(vars__);
    int current_statement__ = 0;
    local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
    // suppress unused var warning
    (void) DUMMY_VAR__;
    try {
      int pos__ = std::numeric_limits<int>::min();
      pos__ = 1;
      Eigen::Matrix<local_scalar_t__,-1,1> alpha_p =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_plate, DUMMY_VAR__);
      current_statement__ = 1;
      stan::model::assign(alpha_p,
        in__.read<Eigen::Matrix<local_scalar_t__,-1,1>>(N_plate),
        "assigning variable alpha_p");
      out__.write(alpha_p);
      Eigen::Matrix<local_scalar_t__,-1,1> mu_group =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_group, DUMMY_VAR__);
      current_statement__ = 2;
      stan::model::assign(mu_group,
        in__.read<Eigen::Matrix<local_scalar_t__,-1,1>>(N_group),
        "assigning variable mu_group");
      out__.write(mu_group);
      local_scalar_t__ sigma_bio = DUMMY_VAR__;
      current_statement__ = 3;
      sigma_bio = in__.read<local_scalar_t__>();
      out__.write_free_lb(0, sigma_bio);
      local_scalar_t__ sigma_tech = DUMMY_VAR__;
      current_statement__ = 4;
      sigma_tech = in__.read<local_scalar_t__>();
      out__.write_free_lb(0, sigma_tech);
      local_scalar_t__ kappa_mu = DUMMY_VAR__;
      current_statement__ = 5;
      kappa_mu = in__.read<local_scalar_t__>();
      out__.write(kappa_mu);
      local_scalar_t__ kappa_sigma = DUMMY_VAR__;
      current_statement__ = 6;
      kappa_sigma = in__.read<local_scalar_t__>();
      out__.write_free_lb(0, kappa_sigma);
      Eigen::Matrix<local_scalar_t__,-1,1> z_1 =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_well, DUMMY_VAR__);
      current_statement__ = 7;
      stan::model::assign(z_1,
        in__.read<Eigen::Matrix<local_scalar_t__,-1,1>>(N_well),
        "assigning variable z_1");
      out__.write(z_1);
      Eigen::Matrix<local_scalar_t__,-1,1> z_2 =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_plate_group,
          DUMMY_VAR__);
      current_statement__ = 8;
      stan::model::assign(z_2,
        in__.read<Eigen::Matrix<local_scalar_t__,-1,1>>(N_plate_group),
        "assigning variable z_2");
      out__.write(z_2);
      Eigen::Matrix<local_scalar_t__,-1,1> z_3 =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_well, DUMMY_VAR__);
      current_statement__ = 9;
      stan::model::assign(z_3,
        in__.read<Eigen::Matrix<local_scalar_t__,-1,1>>(N_well),
        "assigning variable z_3");
      out__.write(z_3);
    } catch (const std::exception& e) {
      stan::lang::rethrow_located(e, locations_array__[current_statement__]);
    }
  }
  template <typename VecVar, stan::require_vector_t<VecVar>* = nullptr>
  inline void
  transform_inits_impl(const stan::io::var_context& context__, VecVar&
                       vars__, std::ostream* pstream__ = nullptr) const {
    using local_scalar_t__ = double;
    stan::io::serializer<local_scalar_t__> out__(vars__);
    int current_statement__ = 0;
    local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
    // suppress unused var warning
    (void) DUMMY_VAR__;
    try {
      current_statement__ = 1;
      context__.validate_dims("parameter initialization", "alpha_p",
        "double", std::vector<size_t>{static_cast<size_t>(N_plate)});
      current_statement__ = 2;
      context__.validate_dims("parameter initialization", "mu_group",
        "double", std::vector<size_t>{static_cast<size_t>(N_group)});
      current_statement__ = 3;
      context__.validate_dims("parameter initialization", "sigma_bio",
        "double", std::vector<size_t>{});
      current_statement__ = 4;
      context__.validate_dims("parameter initialization", "sigma_tech",
        "double", std::vector<size_t>{});
      current_statement__ = 5;
      context__.validate_dims("parameter initialization", "kappa_mu",
        "double", std::vector<size_t>{});
      current_statement__ = 6;
      context__.validate_dims("parameter initialization", "kappa_sigma",
        "double", std::vector<size_t>{});
      current_statement__ = 7;
      context__.validate_dims("parameter initialization", "z_1", "double",
        std::vector<size_t>{static_cast<size_t>(N_well)});
      current_statement__ = 8;
      context__.validate_dims("parameter initialization", "z_2", "double",
        std::vector<size_t>{static_cast<size_t>(N_plate_group)});
      current_statement__ = 9;
      context__.validate_dims("parameter initialization", "z_3", "double",
        std::vector<size_t>{static_cast<size_t>(N_well)});
      int pos__ = std::numeric_limits<int>::min();
      pos__ = 1;
      Eigen::Matrix<local_scalar_t__,-1,1> alpha_p =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_plate, DUMMY_VAR__);
      {
        std::vector<local_scalar_t__> alpha_p_flat__;
        current_statement__ = 1;
        alpha_p_flat__ = context__.vals_r("alpha_p");
        current_statement__ = 1;
        pos__ = 1;
        current_statement__ = 1;
        for (int sym1__ = 1; sym1__ <= N_plate; ++sym1__) {
          current_statement__ = 1;
          stan::model::assign(alpha_p, alpha_p_flat__[(pos__ - 1)],
            "assigning variable alpha_p", stan::model::index_uni(sym1__));
          current_statement__ = 1;
          pos__ = (pos__ + 1);
        }
      }
      out__.write(alpha_p);
      Eigen::Matrix<local_scalar_t__,-1,1> mu_group =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_group, DUMMY_VAR__);
      {
        std::vector<local_scalar_t__> mu_group_flat__;
        current_statement__ = 2;
        mu_group_flat__ = context__.vals_r("mu_group");
        current_statement__ = 2;
        pos__ = 1;
        current_statement__ = 2;
        for (int sym1__ = 1; sym1__ <= N_group; ++sym1__) {
          current_statement__ = 2;
          stan::model::assign(mu_group, mu_group_flat__[(pos__ - 1)],
            "assigning variable mu_group", stan::model::index_uni(sym1__));
          current_statement__ = 2;
          pos__ = (pos__ + 1);
        }
      }
      out__.write(mu_group);
      local_scalar_t__ sigma_bio = DUMMY_VAR__;
      current_statement__ = 3;
      sigma_bio = context__.vals_r("sigma_bio")[(1 - 1)];
      out__.write_free_lb(0, sigma_bio);
      local_scalar_t__ sigma_tech = DUMMY_VAR__;
      current_statement__ = 4;
      sigma_tech = context__.vals_r("sigma_tech")[(1 - 1)];
      out__.write_free_lb(0, sigma_tech);
      local_scalar_t__ kappa_mu = DUMMY_VAR__;
      current_statement__ = 5;
      kappa_mu = context__.vals_r("kappa_mu")[(1 - 1)];
      out__.write(kappa_mu);
      local_scalar_t__ kappa_sigma = DUMMY_VAR__;
      current_statement__ = 6;
      kappa_sigma = context__.vals_r("kappa_sigma")[(1 - 1)];
      out__.write_free_lb(0, kappa_sigma);
      Eigen::Matrix<local_scalar_t__,-1,1> z_1 =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_well, DUMMY_VAR__);
      {
        std::vector<local_scalar_t__> z_1_flat__;
        current_statement__ = 7;
        z_1_flat__ = context__.vals_r("z_1");
        current_statement__ = 7;
        pos__ = 1;
        current_statement__ = 7;
        for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
          current_statement__ = 7;
          stan::model::assign(z_1, z_1_flat__[(pos__ - 1)],
            "assigning variable z_1", stan::model::index_uni(sym1__));
          current_statement__ = 7;
          pos__ = (pos__ + 1);
        }
      }
      out__.write(z_1);
      Eigen::Matrix<local_scalar_t__,-1,1> z_2 =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_plate_group,
          DUMMY_VAR__);
      {
        std::vector<local_scalar_t__> z_2_flat__;
        current_statement__ = 8;
        z_2_flat__ = context__.vals_r("z_2");
        current_statement__ = 8;
        pos__ = 1;
        current_statement__ = 8;
        for (int sym1__ = 1; sym1__ <= N_plate_group; ++sym1__) {
          current_statement__ = 8;
          stan::model::assign(z_2, z_2_flat__[(pos__ - 1)],
            "assigning variable z_2", stan::model::index_uni(sym1__));
          current_statement__ = 8;
          pos__ = (pos__ + 1);
        }
      }
      out__.write(z_2);
      Eigen::Matrix<local_scalar_t__,-1,1> z_3 =
        Eigen::Matrix<local_scalar_t__,-1,1>::Constant(N_well, DUMMY_VAR__);
      {
        std::vector<local_scalar_t__> z_3_flat__;
        current_statement__ = 9;
        z_3_flat__ = context__.vals_r("z_3");
        current_statement__ = 9;
        pos__ = 1;
        current_statement__ = 9;
        for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
          current_statement__ = 9;
          stan::model::assign(z_3, z_3_flat__[(pos__ - 1)],
            "assigning variable z_3", stan::model::index_uni(sym1__));
          current_statement__ = 9;
          pos__ = (pos__ + 1);
        }
      }
      out__.write(z_3);
    } catch (const std::exception& e) {
      stan::lang::rethrow_located(e, locations_array__[current_statement__]);
    }
  }
  inline void
  get_param_names(std::vector<std::string>& names__, const bool
                  emit_transformed_parameters__ = true, const bool
                  emit_generated_quantities__ = true) const {
    names__ = std::vector<std::string>{"alpha_p", "mu_group", "sigma_bio",
                "sigma_tech", "kappa_mu", "kappa_sigma", "z_1", "z_2", "z_3"};
    if (emit_transformed_parameters__) {
      std::vector<std::string>
        temp{"kappa", "mu", "mu_well", "mu_plate_group"};
      names__.reserve(names__.size() + temp.size());
      names__.insert(names__.end(), temp.begin(), temp.end());
    }
    if (emit_generated_quantities__) {
      std::vector<std::string> temp{"y_hat_sample", "log_lik"};
      names__.reserve(names__.size() + temp.size());
      names__.insert(names__.end(), temp.begin(), temp.end());
    }
  }
  inline void
  get_dims(std::vector<std::vector<size_t>>& dimss__, const bool
           emit_transformed_parameters__ = true, const bool
           emit_generated_quantities__ = true) const {
    dimss__ = std::vector<std::vector<size_t>>{std::vector<size_t>{static_cast<
                                                                    size_t>(
                                                                    N_plate)},
                std::vector<size_t>{static_cast<size_t>(N_group)},
                std::vector<size_t>{}, std::vector<size_t>{},
                std::vector<size_t>{}, std::vector<size_t>{},
                std::vector<size_t>{static_cast<size_t>(N_well)},
                std::vector<size_t>{static_cast<size_t>(N_plate_group)},
                std::vector<size_t>{static_cast<size_t>(N_well)}};
    if (emit_transformed_parameters__) {
      std::vector<std::vector<size_t>>
        temp{std::vector<size_t>{static_cast<size_t>(N_well)},
             std::vector<size_t>{static_cast<size_t>(N_well)},
             std::vector<size_t>{static_cast<size_t>(N_well)},
             std::vector<size_t>{static_cast<size_t>(N_plate_group)}};
      dimss__.reserve(dimss__.size() + temp.size());
      dimss__.insert(dimss__.end(), temp.begin(), temp.end());
    }
    if (emit_generated_quantities__) {
      std::vector<std::vector<size_t>>
        temp{std::vector<size_t>{static_cast<size_t>(N_well)},
             std::vector<size_t>{static_cast<size_t>(N)}};
      dimss__.reserve(dimss__.size() + temp.size());
      dimss__.insert(dimss__.end(), temp.begin(), temp.end());
    }
  }
  inline void
  constrained_param_names(std::vector<std::string>& param_names__, bool
                          emit_transformed_parameters__ = true, bool
                          emit_generated_quantities__ = true) const final {
    for (int sym1__ = 1; sym1__ <= N_plate; ++sym1__) {
      param_names__.emplace_back(std::string() + "alpha_p" + '.' +
        std::to_string(sym1__));
    }
    for (int sym1__ = 1; sym1__ <= N_group; ++sym1__) {
      param_names__.emplace_back(std::string() + "mu_group" + '.' +
        std::to_string(sym1__));
    }
    param_names__.emplace_back(std::string() + "sigma_bio");
    param_names__.emplace_back(std::string() + "sigma_tech");
    param_names__.emplace_back(std::string() + "kappa_mu");
    param_names__.emplace_back(std::string() + "kappa_sigma");
    for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
      param_names__.emplace_back(std::string() + "z_1" + '.' +
        std::to_string(sym1__));
    }
    for (int sym1__ = 1; sym1__ <= N_plate_group; ++sym1__) {
      param_names__.emplace_back(std::string() + "z_2" + '.' +
        std::to_string(sym1__));
    }
    for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
      param_names__.emplace_back(std::string() + "z_3" + '.' +
        std::to_string(sym1__));
    }
    if (emit_transformed_parameters__) {
      for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
        param_names__.emplace_back(std::string() + "kappa" + '.' +
          std::to_string(sym1__));
      }
      for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
        param_names__.emplace_back(std::string() + "mu" + '.' +
          std::to_string(sym1__));
      }
      for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
        param_names__.emplace_back(std::string() + "mu_well" + '.' +
          std::to_string(sym1__));
      }
      for (int sym1__ = 1; sym1__ <= N_plate_group; ++sym1__) {
        param_names__.emplace_back(std::string() + "mu_plate_group" + '.' +
          std::to_string(sym1__));
      }
    }
    if (emit_generated_quantities__) {
      for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
        param_names__.emplace_back(std::string() + "y_hat_sample" + '.' +
          std::to_string(sym1__));
      }
      for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
        param_names__.emplace_back(std::string() + "log_lik" + '.' +
          std::to_string(sym1__));
      }
    }
  }
  inline void
  unconstrained_param_names(std::vector<std::string>& param_names__, bool
                            emit_transformed_parameters__ = true, bool
                            emit_generated_quantities__ = true) const final {
    for (int sym1__ = 1; sym1__ <= N_plate; ++sym1__) {
      param_names__.emplace_back(std::string() + "alpha_p" + '.' +
        std::to_string(sym1__));
    }
    for (int sym1__ = 1; sym1__ <= N_group; ++sym1__) {
      param_names__.emplace_back(std::string() + "mu_group" + '.' +
        std::to_string(sym1__));
    }
    param_names__.emplace_back(std::string() + "sigma_bio");
    param_names__.emplace_back(std::string() + "sigma_tech");
    param_names__.emplace_back(std::string() + "kappa_mu");
    param_names__.emplace_back(std::string() + "kappa_sigma");
    for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
      param_names__.emplace_back(std::string() + "z_1" + '.' +
        std::to_string(sym1__));
    }
    for (int sym1__ = 1; sym1__ <= N_plate_group; ++sym1__) {
      param_names__.emplace_back(std::string() + "z_2" + '.' +
        std::to_string(sym1__));
    }
    for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
      param_names__.emplace_back(std::string() + "z_3" + '.' +
        std::to_string(sym1__));
    }
    if (emit_transformed_parameters__) {
      for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
        param_names__.emplace_back(std::string() + "kappa" + '.' +
          std::to_string(sym1__));
      }
      for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
        param_names__.emplace_back(std::string() + "mu" + '.' +
          std::to_string(sym1__));
      }
      for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
        param_names__.emplace_back(std::string() + "mu_well" + '.' +
          std::to_string(sym1__));
      }
      for (int sym1__ = 1; sym1__ <= N_plate_group; ++sym1__) {
        param_names__.emplace_back(std::string() + "mu_plate_group" + '.' +
          std::to_string(sym1__));
      }
    }
    if (emit_generated_quantities__) {
      for (int sym1__ = 1; sym1__ <= N_well; ++sym1__) {
        param_names__.emplace_back(std::string() + "y_hat_sample" + '.' +
          std::to_string(sym1__));
      }
      for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
        param_names__.emplace_back(std::string() + "log_lik" + '.' +
          std::to_string(sym1__));
      }
    }
  }
  inline std::string get_constrained_sizedtypes() const {
    return std::string("[{\"name\":\"alpha_p\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_plate) + "},\"block\":\"parameters\"},{\"name\":\"mu_group\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_group) + "},\"block\":\"parameters\"},{\"name\":\"sigma_bio\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"},{\"name\":\"sigma_tech\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"},{\"name\":\"kappa_mu\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"},{\"name\":\"kappa_sigma\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"},{\"name\":\"z_1\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_well) + "},\"block\":\"parameters\"},{\"name\":\"z_2\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_plate_group) + "},\"block\":\"parameters\"},{\"name\":\"z_3\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_well) + "},\"block\":\"parameters\"},{\"name\":\"kappa\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_well) + "},\"block\":\"transformed_parameters\"},{\"name\":\"mu\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_well) + "},\"block\":\"transformed_parameters\"},{\"name\":\"mu_well\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_well) + "},\"block\":\"transformed_parameters\"},{\"name\":\"mu_plate_group\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_plate_group) + "},\"block\":\"transformed_parameters\"},{\"name\":\"y_hat_sample\",\"type\":{\"name\":\"array\",\"length\":" + std::to_string(N_well) + ",\"element_type\":{\"name\":\"real\"}},\"block\":\"generated_quantities\"},{\"name\":\"log_lik\",\"type\":{\"name\":\"array\",\"length\":" + std::to_string(N) + ",\"element_type\":{\"name\":\"real\"}},\"block\":\"generated_quantities\"}]");
  }
  inline std::string get_unconstrained_sizedtypes() const {
    return std::string("[{\"name\":\"alpha_p\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_plate) + "},\"block\":\"parameters\"},{\"name\":\"mu_group\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_group) + "},\"block\":\"parameters\"},{\"name\":\"sigma_bio\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"},{\"name\":\"sigma_tech\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"},{\"name\":\"kappa_mu\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"},{\"name\":\"kappa_sigma\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"},{\"name\":\"z_1\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_well) + "},\"block\":\"parameters\"},{\"name\":\"z_2\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_plate_group) + "},\"block\":\"parameters\"},{\"name\":\"z_3\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_well) + "},\"block\":\"parameters\"},{\"name\":\"kappa\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_well) + "},\"block\":\"transformed_parameters\"},{\"name\":\"mu\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_well) + "},\"block\":\"transformed_parameters\"},{\"name\":\"mu_well\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_well) + "},\"block\":\"transformed_parameters\"},{\"name\":\"mu_plate_group\",\"type\":{\"name\":\"vector\",\"length\":" + std::to_string(N_plate_group) + "},\"block\":\"transformed_parameters\"},{\"name\":\"y_hat_sample\",\"type\":{\"name\":\"array\",\"length\":" + std::to_string(N_well) + ",\"element_type\":{\"name\":\"real\"}},\"block\":\"generated_quantities\"},{\"name\":\"log_lik\",\"type\":{\"name\":\"array\",\"length\":" + std::to_string(N) + ",\"element_type\":{\"name\":\"real\"}},\"block\":\"generated_quantities\"}]");
  }
  // Begin method overload boilerplate
  template <typename RNG> inline void
  write_array(RNG& base_rng, Eigen::Matrix<double,-1,1>& params_r,
              Eigen::Matrix<double,-1,1>& vars, const bool
              emit_transformed_parameters = true, const bool
              emit_generated_quantities = true, std::ostream*
              pstream = nullptr) const {
    const size_t num_params__ = ((((((((N_plate + N_group) + 1) + 1) + 1) +
      1) + N_well) + N_plate_group) + N_well);
    const size_t num_transformed = emit_transformed_parameters * ((((N_well +
      N_well) + N_well) + N_plate_group));
    const size_t num_gen_quantities = emit_generated_quantities * ((N_well +
      N));
    const size_t num_to_write = num_params__ + num_transformed +
      num_gen_quantities;
    std::vector<int> params_i;
    vars = Eigen::Matrix<double,-1,1>::Constant(num_to_write,
             std::numeric_limits<double>::quiet_NaN());
    write_array_impl(base_rng, params_r, params_i, vars,
      emit_transformed_parameters, emit_generated_quantities, pstream);
  }
  template <typename RNG> inline void
  write_array(RNG& base_rng, std::vector<double>& params_r, std::vector<int>&
              params_i, std::vector<double>& vars, bool
              emit_transformed_parameters = true, bool
              emit_generated_quantities = true, std::ostream*
              pstream = nullptr) const {
    const size_t num_params__ = ((((((((N_plate + N_group) + 1) + 1) + 1) +
      1) + N_well) + N_plate_group) + N_well);
    const size_t num_transformed = emit_transformed_parameters * ((((N_well +
      N_well) + N_well) + N_plate_group));
    const size_t num_gen_quantities = emit_generated_quantities * ((N_well +
      N));
    const size_t num_to_write = num_params__ + num_transformed +
      num_gen_quantities;
    vars = std::vector<double>(num_to_write,
             std::numeric_limits<double>::quiet_NaN());
    write_array_impl(base_rng, params_r, params_i, vars,
      emit_transformed_parameters, emit_generated_quantities, pstream);
  }
  template <bool propto__, bool jacobian__, typename T_> inline T_
  log_prob(Eigen::Matrix<T_,-1,1>& params_r, std::ostream* pstream = nullptr) const {
    Eigen::Matrix<int,-1,1> params_i;
    return log_prob_impl<propto__, jacobian__>(params_r, params_i, pstream);
  }
  template <bool propto__, bool jacobian__, typename T_> inline T_
  log_prob(std::vector<T_>& params_r, std::vector<int>& params_i,
           std::ostream* pstream = nullptr) const {
    return log_prob_impl<propto__, jacobian__>(params_r, params_i, pstream);
  }
  inline void
  transform_inits(const stan::io::var_context& context,
                  Eigen::Matrix<double,-1,1>& params_r, std::ostream*
                  pstream = nullptr) const final {
    std::vector<double> params_r_vec(params_r.size());
    std::vector<int> params_i;
    transform_inits(context, params_i, params_r_vec, pstream);
    params_r = Eigen::Map<Eigen::Matrix<double,-1,1>>(params_r_vec.data(),
                 params_r_vec.size());
  }
  inline void
  transform_inits(const stan::io::var_context& context, std::vector<int>&
                  params_i, std::vector<double>& vars, std::ostream*
                  pstream__ = nullptr) const {
    vars.resize(num_params_r__);
    transform_inits_impl(context, vars, pstream__);
  }
  inline void
  unconstrain_array(const std::vector<double>& params_constrained,
                    std::vector<double>& params_unconstrained, std::ostream*
                    pstream = nullptr) const {
    const std::vector<int> params_i;
    params_unconstrained = std::vector<double>(num_params_r__,
                             std::numeric_limits<double>::quiet_NaN());
    unconstrain_array_impl(params_constrained, params_i,
      params_unconstrained, pstream);
  }
  inline void
  unconstrain_array(const Eigen::Matrix<double,-1,1>& params_constrained,
                    Eigen::Matrix<double,-1,1>& params_unconstrained,
                    std::ostream* pstream = nullptr) const {
    const std::vector<int> params_i;
    params_unconstrained = Eigen::Matrix<double,-1,1>::Constant(num_params_r__,
                             std::numeric_limits<double>::quiet_NaN());
    unconstrain_array_impl(params_constrained, params_i,
      params_unconstrained, pstream);
  }
};
}
using stan_model = model_M_namespace::model_M;
#ifndef USING_R
// Boilerplate
stan::model::model_base&
new_model(stan::io::var_context& data_context, unsigned int seed,
          std::ostream* msg_stream) {
  stan_model* m = new stan_model(data_context, seed, msg_stream);
  return *m;
}
stan::math::profile_map& get_stan_profile_data() {
  return model_M_namespace::profiles__;
}
#endif
#endif
