def biogas_combustion(biogas, emission_offsets, income, parameters, correlation_distributions, correlation_parameters, exchange_rate, n_samples): # biogas losses from fittings, etc. loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.biogas_loss, correlation_distributions, correlation_parameters, n_samples) biogas_delivered = biogas * ((100 - loss) / 100) # income from biogas sale (USD/cap/yr) if parameters.biogas_sale.expected == 'yes': selling_price, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.LPG_selling_price, correlation_distributions, correlation_parameters, n_samples) specific_energy, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.LPG_specific_energy, correlation_distributions, correlation_parameters, n_samples) income_biogas = (biogas_delivered / 1000) * ( (selling_price / specific_energy) / exchange_rate) income[:, 4:] = income[:, 4:] + income_biogas # emissions offsets if parameters.biogas_offsets.expected == 'yes': emission_factor, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.LPG_emissions, correlation_distributions, correlation_parameters, n_samples) offsets_biogas = (biogas_delivered / 1000) * (emission_factor / specific_energy) emission_offsets[:, 4:] = emission_offsets[:, 4:] + offsets_biogas # combustion efficiency if parameters.consider_combustion_efficiency.expected == 'yes': efficiency, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.efficiency_biogas, correlation_distributions, correlation_parameters, n_samples) biogas_output = biogas_delivered * (efficiency / 100) else: biogas_output = copy.deepcopy(biogas_delivered) return biogas_output, emission_offsets, income, correlation_distributions, correlation_parameters
def UDDT(urine_inputs, feces_inputs, parameters, construction_cost, operating_cost, tech_construction_emissions, tech_operating_emissions, correlation_distributions, correlation_parameters, n_samples, discount_rate): # separate out input variables from concatenated arrays urine_input = np.reshape(urine_inputs[:, 0], (-1, 1)) urine_dry_input = np.reshape(urine_inputs[:, 1], (-1, 1)) N_urine_input = np.reshape(urine_inputs[:, 2], (-1, 1)) P_urine_input = np.reshape(urine_inputs[:, 3], (-1, 1)) K_urine_input = np.reshape(urine_inputs[:, 4], (-1, 1)) Mg_urine_input = np.reshape(urine_inputs[:, 5], (-1, 1)) Ca_urine_input = np.reshape(urine_inputs[:, 6], (-1, 1)) energy_urine_input = np.reshape(urine_inputs[:, 7], (-1, 1)) N_ammonia_urine_input = np.reshape(urine_inputs[:, 8], (-1, 1)) feces_input = np.reshape(feces_inputs[:, 0], (-1, 1)) feces_dry_input = np.reshape(feces_inputs[:, 1], (-1, 1)) N_feces_input = np.reshape(feces_inputs[:, 2], (-1, 1)) P_feces_input = np.reshape(feces_inputs[:, 3], (-1, 1)) K_feces_input = np.reshape(feces_inputs[:, 4], (-1, 1)) Mg_feces_input = np.reshape(feces_inputs[:, 5], (-1, 1)) Ca_feces_input = np.reshape(feces_inputs[:, 6], (-1, 1)) energy_feces_input = np.reshape(feces_inputs[:, 7], (-1, 1)) N_ammonia_feces_input = np.reshape(feces_inputs[:, 8], (-1, 1)) # generate distributions of parameters # cleansing material: toilet paper if parameters.toilet_paper.expected == 'yes': toilet_paper_addition, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.toilet_paper_addition, correlation_distributions, correlation_parameters, n_samples) toilet_paper_COD_content, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.toilet_paper_COD_content, correlation_distributions, correlation_parameters, n_samples) toilet_paper_N_content, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.toilet_paper_N_content, correlation_distributions, correlation_parameters, n_samples) toilet_paper_P_content, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.toilet_paper_P_content, correlation_distributions, correlation_parameters, n_samples) toilet_paper_K_content, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.toilet_paper_K_content, correlation_distributions, correlation_parameters, n_samples) toilet_paper_TS_content, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.toilet_paper_TS_content, correlation_distributions, correlation_parameters, n_samples) elif parameters.toilet_paper.expected == 'no': toilet_paper_addition = 0 toilet_paper_COD_content = 0 toilet_paper_N_content = 0 toilet_paper_P_content = 0 toilet_paper_K_content = 0 toilet_paper_TS_content = 0 # flushing water if parameters.flushing_water.expected == 'yes': flushing_water_addition, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.flushing_water_use, correlation_distributions, correlation_parameters, n_samples) elif parameters.flushing_water.expected == 'no': flushing_water_addition = 0 # cleansing material: water if (parameters.cleansing_water.expected == 'yes') and (parameters.cleansing_water_hole.expected == 'no'): cleansing_water_addition, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.cleansing_water_use, correlation_distributions, correlation_parameters, n_samples) else: cleansing_water_addition = 0 # desiccant if parameters.desiccant.expected == 'yes': desiccant_volume, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.desiccant_volume, correlation_distributions, correlation_parameters, n_samples) desiccant_density, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.desiccant_density, correlation_distributions, correlation_parameters, n_samples) desiccant_C_N_ratio, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.desiccant_C_N_ratio, correlation_distributions, correlation_parameters, n_samples) desiccant_N_content, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.desiccant_N_content, correlation_distributions, correlation_parameters, n_samples) desiccant_P_content, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.desiccant_P_content, correlation_distributions, correlation_parameters, n_samples) desiccant_K_content, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.desiccant_K_content, correlation_distributions, correlation_parameters, n_samples) desiccant_Mg_content, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.desiccant_Mg_content, correlation_distributions, correlation_parameters, n_samples) desiccant_Ca_content, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.desiccant_Ca_content, correlation_distributions, correlation_parameters, n_samples) elif parameters.desiccant.expected == 'no': desiccant_volume = 0 desiccant_density = 0 desiccant_N_content = 0 desiccant_P_content = 0 desiccant_K_content = 0 desiccant_Mg_content = 0 desiccant_Ca_content = 0 # household and toilet characteristics household_size, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.household_size, correlation_distributions, correlation_parameters, n_samples) household_use_density, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.household_use_density, correlation_distributions, correlation_parameters, n_samples) # calculate resources in materials added by user (per capita per year) # N (kg N/cap/yr) additives_N = ( (toilet_paper_addition * toilet_paper_N_content * 365 / 1000000) + (desiccant_volume * desiccant_density * (desiccant_N_content / 100) * 365 / 1000000)) # P (kg P/cap/yr) additives_P = ( (toilet_paper_addition * toilet_paper_P_content * 365 / 1000000) + (desiccant_volume * desiccant_density * (desiccant_P_content / 100) * 365 / 1000000)) # K (kg K/cap/yr) additives_K = ( (toilet_paper_addition * toilet_paper_K_content * 365 / 1000000) + (desiccant_volume * desiccant_density * (desiccant_K_content / 100) * 365 / 1000000)) # Mg (kg Mg/cap/yr) additives_Mg = (desiccant_volume * desiccant_density * (desiccant_Mg_content / 100) * 365 / 1000000) # Ca (kg Ca/cap/yr) additives_Ca = (desiccant_volume * desiccant_density * (desiccant_Ca_content / 100) * 365 / 1000000) # energy (kJ/cap/yr) - assume desiccant contains no additional energy (wood ash), so only include TP # - also assume 3.86 kWh energy production per kg COD oxidized to CO2 and H20 additives_energy = toilet_paper_addition * toilet_paper_COD_content * 365 / 1000000 * 3.86 * 3600 # total per capita addition (kg/cap/yr) additives_input = ( (toilet_paper_addition * toilet_paper_TS_content * 365 / 1000000) + (desiccant_volume * desiccant_density * 365 / 1000000)) # total water input (L/cap/yr) water_input = (flushing_water_addition + cleansing_water_addition) * 365 # total dry addition (kg/cap/yr) - assume toilet paper and desiccant have moisture content ~ 0% additives_dry_input = ( (toilet_paper_addition * toilet_paper_TS_content * 365 / 1000000) + (desiccant_volume * desiccant_density * 365 / 1000000)) # mix materials together to form two streams (urine, feces) from all HHs using toilet - total input per year # nitrogen (kg N/cap/yr) N_urine = (N_urine_input) N_feces = (N_feces_input + additives_N) # phosphorus (kg P/cap/yr) P_urine = (P_urine_input) P_feces = (P_feces_input + additives_P) # potassium (kg K/cap/yr) K_urine = (K_urine_input) K_feces = (K_feces_input + additives_K) # magnesium (kg Mg/cap/yr) Mg_urine = (Mg_urine_input) Mg_feces = (Mg_feces_input + additives_Mg) # calcium (kg Ca/cap/yr) Ca_urine = (Ca_urine_input) Ca_feces = (Ca_feces_input + additives_Ca) # energy (kJ/cap/yr) energy_urine = (energy_urine_input) energy_feces = (energy_feces_input + additives_energy) # ammonia (kg N/cap/yr) N_ammonia_urine = N_ammonia_urine_input N_ammonia_feces = N_ammonia_feces_input # total excreta input (kg/cap/yr) urine_total = (urine_input) # if design includes a separate hole for cleansing water, do not include it with fecal stream feces_total = (feces_input + additives_input + water_input) # total dry excreta input (kg/cap/yr) urine_dry = (urine_dry_input) feces_dry = (feces_dry_input + additives_dry_input) # concatenate excreta outputs to simplify function output urine_outputs = np.concatenate( (urine_total, urine_dry, N_urine, P_urine, K_urine, Mg_urine, Ca_urine, energy_urine, N_ammonia_urine), 1) feces_outputs = np.concatenate( (feces_total, feces_dry, N_feces, P_feces, K_feces, Mg_feces, Ca_feces, energy_feces, N_ammonia_feces), 1) # users number_users = household_use_density * household_size # cost for one facility capex, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.UDDT_capex, correlation_distributions, correlation_parameters, n_samples) opex_percent, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.UDDT_opex, correlation_distributions, correlation_parameters, n_samples) lifetime, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.toilet_lifetime, correlation_distributions, correlation_parameters, n_samples) annual_opex = (capex * (opex_percent / 100)) / number_users capex_annualized = (capex * ((discount_rate * (1 + discount_rate)**lifetime) / (((1 + discount_rate)**lifetime) - 1))) / number_users construction_cost[:, :1] = construction_cost[:, :1] + capex_annualized operating_cost[:, :1] = operating_cost[:, :1] + annual_opex # GHG emissions from construction cement, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.cement_UDDT, correlation_distributions, correlation_parameters, n_samples) gravel, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.gravel_UDDT, correlation_distributions, correlation_parameters, n_samples) sand, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.sand_UDDT, correlation_distributions, correlation_parameters, n_samples) bricks, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.bricks_UDDT, correlation_distributions, correlation_parameters, n_samples) plastic, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.plastic_UDDT, correlation_distributions, correlation_parameters, n_samples) steel, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.steel_UDDT, correlation_distributions, correlation_parameters, n_samples) stainless_steel_sheet, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.stainless_steel_sheet_UDDT, correlation_distributions, correlation_parameters, n_samples) wood, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.wood_UDDT, correlation_distributions, correlation_parameters, n_samples) plastic_mass, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.plastic_mass, correlation_distributions, correlation_parameters, n_samples) brick_volume, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.brick_volume, correlation_distributions, correlation_parameters, n_samples) brick_density, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.brick_density, correlation_distributions, correlation_parameters, n_samples) steel_sheet_mass, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.steel_sheet_mass, correlation_distributions, correlation_parameters, n_samples) gravel_density, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.gravel_bulk_density, correlation_distributions, correlation_parameters, n_samples) sand_density, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.sand_bulk_density, correlation_distributions, correlation_parameters, n_samples) steel_density, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.steel_density, correlation_distributions, correlation_parameters, n_samples) steel_IF_GHG, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.steel_IF_GHG, correlation_distributions, correlation_parameters, n_samples) stainless_steel_IF_GHG, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.stainless_steel_IF_GHG, correlation_distributions, correlation_parameters, n_samples) stainless_steel_sheet_IF_GHG, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.stainless_steel_sheet_IF_GHG, correlation_distributions, correlation_parameters, n_samples) plastic_IF_GHG, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.plastic_IF_GHG, correlation_distributions, correlation_parameters, n_samples) gravel_IF_GHG, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.gravel_IF_GHG, correlation_distributions, correlation_parameters, n_samples) sand_IF_GHG, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.sand_IF_GHG, correlation_distributions, correlation_parameters, n_samples) cement_IF_GHG, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.cement_IF_GHG, correlation_distributions, correlation_parameters, n_samples) bricks_IF_GHG, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.bricks_IF_GHG, correlation_distributions, correlation_parameters, n_samples) wood_IF_GHG, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.wood_IF_GHG, correlation_distributions, correlation_parameters, n_samples) cement_emissions = cement * cement_IF_GHG gravel_emissions = gravel * gravel_density * gravel_IF_GHG sand_emissions = sand * sand_density * sand_IF_GHG brick_emissions = bricks * brick_volume * brick_density * bricks_IF_GHG plastic_emissions = plastic * plastic_mass * plastic_IF_GHG steel_emissions = steel * steel_density * steel_IF_GHG stainless_steel_emissions = stainless_steel_sheet * steel_sheet_mass * ( stainless_steel_IF_GHG + stainless_steel_sheet_IF_GHG) wood_emissions = wood * wood_IF_GHG construction_emissions_annual = ( (cement_emissions + gravel_emissions + sand_emissions + brick_emissions + plastic_emissions + steel_emissions + stainless_steel_emissions + wood_emissions) / lifetime / number_users) tech_construction_emissions[:, : 1] = tech_construction_emissions[:, : 1] + construction_emissions_annual return urine_outputs, feces_outputs, construction_cost, operating_cost, tech_construction_emissions, tech_operating_emissions, correlation_distributions, correlation_parameters, number_users
def human_inputs(initial_inputs, correlation_distributions, correlation_parameters, n_samples): # create uncertainty distributions using Latin Hypercube Sampling # use the LHS distribution function to identify and generate desired distributions caloric_intake, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.caloric_intake, correlation_distributions, correlation_parameters, n_samples) protein_vegetal_intake, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.protein_vegetal_intake, correlation_distributions, correlation_parameters, n_samples) protein_animal_intake, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.protein_animal_intake, correlation_distributions, correlation_parameters, n_samples) N_content_protein, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.N_content_protein, correlation_distributions, correlation_parameters, n_samples) P_content_protein_vegetal, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.P_content_protein_vegetal, correlation_distributions, correlation_parameters, n_samples) P_content_protein_animal, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.P_content_protein_animal, correlation_distributions, correlation_parameters, n_samples) K_content_caloric_intake, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.K_content_caloric_intake, correlation_distributions, correlation_parameters, n_samples) N_excretion, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.N_excretion, correlation_distributions, correlation_parameters, n_samples) P_excretion, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.P_excretion, correlation_distributions, correlation_parameters, n_samples) K_excretion, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.K_excretion, correlation_distributions, correlation_parameters, n_samples) energy_excretion, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.energy_excretion, correlation_distributions, correlation_parameters, n_samples) N_in_urine, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.N_in_urine, correlation_distributions, correlation_parameters, n_samples) P_in_urine, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.P_in_urine, correlation_distributions, correlation_parameters, n_samples) K_in_urine, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.K_in_urine, correlation_distributions, correlation_parameters, n_samples) energy_in_feces, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.energy_in_feces, correlation_distributions, correlation_parameters, n_samples) urine_excretion, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.urine_excretion, correlation_distributions, correlation_parameters, n_samples) feces_excretion, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.feces_excretion, correlation_distributions, correlation_parameters, n_samples) urine_moisture_content, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.urine_moisture_content, correlation_distributions, correlation_parameters, n_samples) feces_moisture_content, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.feces_moisture_content, correlation_distributions, correlation_parameters, n_samples) Mg_in_urine, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.Mg_in_urine, correlation_distributions, correlation_parameters, n_samples) Mg_in_feces, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.Mg_in_feces, correlation_distributions, correlation_parameters, n_samples) Ca_in_urine, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.Ca_in_urine, correlation_distributions, correlation_parameters, n_samples) Ca_in_feces, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.Ca_in_feces, correlation_distributions, correlation_parameters, n_samples) N_ammonia_in_urine, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.N_reduced_inorganic_in_urine, correlation_distributions, correlation_parameters, n_samples) N_ammonia_in_feces, correlation_distributions, correlation_parameters = lhs.lhs_distribution(initial_inputs.N_reduced_inorganic_in_feces, correlation_distributions, correlation_parameters, n_samples) # calculate resources in urine and feces excreted by a person # urine # nitrogen (kg N/yr) N_urine_input = ((protein_vegetal_intake + protein_animal_intake) * (N_content_protein / 100) * (N_excretion / 100) * (N_in_urine / 100) * 365 / 1000) # phosphorus (kg P/yr) P_urine_input = (((protein_vegetal_intake * (P_content_protein_vegetal / 100)) + (protein_animal_intake * (P_content_protein_animal / 100))) * (P_excretion / 100) * (P_in_urine / 100) * 365 / 1000) # potassium (kg K/yr) K_urine_input = (((caloric_intake / 1000) * K_content_caloric_intake) * (K_excretion / 100) * (K_in_urine / 100) * 365 / 1000) # magnesium (kg Mg/yr) Mg_urine_input = Mg_in_urine * 365 / 1000 # calcium (kg Ca/yr) Ca_urine_input = Ca_in_urine * 365 / 1000 # energy (kJ/yr) energy_urine_input = (caloric_intake * (energy_excretion / 100) * ((100 - energy_in_feces) / 100) * 365 * 4.184) # total household excretion (kg/yr) urine_input = urine_excretion * 365 / 1000 # total dry matter household excretion (kg/yr) urine_dry_input = urine_input * ((100 - urine_moisture_content) / 100) # total ammonia (kg N/yr) N_ammonia_urine = N_urine_input * (N_ammonia_in_urine / 100) # feces # nitrogen (kg N/yr) N_feces_input = ((protein_vegetal_intake + protein_animal_intake) * (N_content_protein / 100) * (N_excretion / 100) * ((100 - N_in_urine) / 100) * 365 / 1000) # phosphorus (kg P/yr) P_feces_input = (((protein_vegetal_intake * (P_content_protein_vegetal / 100)) + (protein_animal_intake * (P_content_protein_animal / 100))) * (P_excretion / 100) * ((100 - P_in_urine) / 100) * 365 / 1000) # potassium (kg K/yr) K_feces_input = (((caloric_intake / 1000) * K_content_caloric_intake) * (K_excretion / 100) * ((100 - K_in_urine) / 100) * 365 / 1000) # magnesium (kg Mg/yr) Mg_feces_input = Mg_in_feces * 365 / 1000 # calcium (kg Ca/yr) Ca_feces_input = Ca_in_feces * 365 / 1000 # energy (kJ/yr) energy_feces_input = (caloric_intake * (energy_excretion / 100) * (energy_in_feces / 100) * 365 * 4.184) # total per capita excretion (kg/yr) feces_input = feces_excretion * 365 / 1000 # total dry matter per capita excretion (kg/yr) feces_dry_input = feces_input * ((100 - feces_moisture_content) / 100) # total ammonia (kg N/yr) N_ammonia_feces = N_feces_input * (N_ammonia_in_feces / 100) # concatenate all urine inputs and all feces inputs to simplify function variables system_urine_inputs = np.concatenate((urine_input, urine_dry_input, N_urine_input, P_urine_input, K_urine_input, Mg_urine_input, Ca_urine_input, energy_urine_input, N_ammonia_urine), 1) system_feces_inputs = np.concatenate((feces_input, feces_dry_input, N_feces_input, P_feces_input, K_feces_input, Mg_feces_input, Ca_feces_input, energy_feces_input, N_ammonia_feces), 1) return system_urine_inputs, system_feces_inputs, correlation_distributions, correlation_parameters
def crop_application(inputs, emission_offsets, income, parameters, correlation_distributions, correlation_parameters, n_samples): # mass and nutrients are recovered, but not energy; this also maintains extra outputs outputs = copy.deepcopy(inputs) mass = np.reshape(inputs[:, 0], (-1, 1)) mass_dry = np.reshape(inputs[:, 1], (-1, 1)) N_total = np.reshape(inputs[:, 2], (-1, 1)) P_total = np.reshape(inputs[:, 3], (-1, 1)) K_total = np.reshape(inputs[:, 4], (-1, 1)) Mg_total = np.reshape(inputs[:, 5], (-1, 1)) Ca_total = np.reshape(inputs[:, 6], (-1, 1)) energy = np.reshape(inputs[:, 7], (-1, 1)) N_amm = np.reshape(inputs[:, 8], (-1, 1)) # income from sale of sludge or liquid if parameters.fertilizer_sale.expected == 'yes': N_price, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N_fertilizer_price, correlation_distributions, correlation_parameters, n_samples) P_price, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.P_fertilizer_price, correlation_distributions, correlation_parameters, n_samples) K_price, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.K_fertilizer_price, correlation_distributions, correlation_parameters, n_samples) discount_factor, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.sludge_fertilizer_discount_factor, correlation_distributions, correlation_parameters, n_samples) income_fertilizer = (((N_total / 1000) * N_price) + ((P_total / 1000) * P_price) + ((K_total / 1000) * K_price)) * discount_factor income[:, 4:] = income[:, 4:] + income_fertilizer # nutrient losses during transfer to cropland if parameters.transfer_losses_application.expected == 'yes': N_amm_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N_amm_loss_application, correlation_distributions, correlation_parameters, n_samples) N_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N_loss_application, correlation_distributions, correlation_parameters, n_samples) P_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.P_loss_application, correlation_distributions, correlation_parameters, n_samples) K_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.K_loss_application, correlation_distributions, correlation_parameters, n_samples) Mg_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.Mg_loss_application, correlation_distributions, correlation_parameters, n_samples) Ca_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.Ca_loss_application, correlation_distributions, correlation_parameters, n_samples) C_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.C_loss_application, correlation_distributions, correlation_parameters, n_samples) else: N_amm_loss = 0 N_loss = 0 P_loss = 0 K_loss = 0 Mg_loss = 0 Ca_loss = 0 C_loss = 0 # compute remaining nutrients after losses N_other_lost = (N_total - N_amm) * (N_loss / 100) N_amm_lost = N_amm * ((N_amm_loss / 100)) N_total_lost = N_other_lost + N_amm_lost P_total_lost = P_total * (P_loss / 100) K_total_lost = K_total * (K_loss / 100) Mg_total_lost = Mg_total * (Mg_loss / 100) Ca_total_lost = Ca_total * (Ca_loss / 100) # correct if N amm loss + other N loss is > 100% for i in range(0, len(N_total)): if N_total[i] < N_total_lost[i]: N_total_lost[i] = N_total[i] N_total = N_total - N_total_lost N_amm = N_amm - N_amm_lost P_total = P_total - P_total_lost K_total = K_total - K_total_lost Mg_total = Mg_total - Mg_total_lost Ca_total = Ca_total - Ca_total_lost energy = energy * ((100 - C_loss) / 100) # fertilizer GHG offsets if parameters.fertilizer_offsets.expected == 'yes': N_emissions, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N_fertilizer_emissions, correlation_distributions, correlation_parameters, n_samples) P_emissions, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.P_fertilizer_emissions, correlation_distributions, correlation_parameters, n_samples) K_emissions, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.K_fertilizer_emissions, correlation_distributions, correlation_parameters, n_samples) nutrient_offsets = N_total * N_emissions + P_total * P_emissions + K_total * K_emissions emission_offsets[:, 4:] = emission_offsets[:, 4:] + nutrient_offsets # return outputs to output matrix outputs[:, 0:9] = np.concatenate( (mass, mass_dry, N_total, P_total, K_total, Mg_total, Ca_total, energy, N_amm), 1) return outputs, emission_offsets, income, correlation_distributions, correlation_parameters
def tanker_truck(inputs, tech_operating_emissions, operating_cost, parameters, correlation_distributions, correlation_parameters, n_samples, rate_constant, maximum_methane_emission, CH4_GWP, N2O_GWP, exchange_rate, discount_rate, number_users, previous_storage_time): # mass and nutrients are recovered; this also maintains extra outputs outputs = copy.deepcopy(inputs) mass = np.reshape(inputs[:, 0], (-1, 1)) mass_dry = np.reshape(inputs[:, 1], (-1, 1)) N_total = np.reshape(inputs[:, 2], (-1, 1)) P_total = np.reshape(inputs[:, 3], (-1, 1)) K_total = np.reshape(inputs[:, 4], (-1, 1)) Mg_total = np.reshape(inputs[:, 5], (-1, 1)) Ca_total = np.reshape(inputs[:, 6], (-1, 1)) energy = np.reshape(inputs[:, 7], (-1, 1)) N_amm = np.reshape(inputs[:, 8], (-1, 1)) # nutrient losses during conveyance if parameters.losses_tanker_truck.expected == 'yes': N_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N_loss_tanker_truck, correlation_distributions, correlation_parameters, n_samples) P_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.P_loss_tanker_truck, correlation_distributions, correlation_parameters, n_samples) K_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.K_loss_tanker_truck, correlation_distributions, correlation_parameters, n_samples) Mg_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.Mg_loss_tanker_truck, correlation_distributions, correlation_parameters, n_samples) Ca_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.Ca_loss_tanker_truck, correlation_distributions, correlation_parameters, n_samples) C_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.C_loss_tanker_truck, correlation_distributions, correlation_parameters, n_samples) else: N_loss = 0 P_loss = 0 K_loss = 0 Mg_loss = 0 Ca_loss = 0 C_loss = 0 # compute remaining nutrients after transfer losses N_total_lost = N_total * (N_loss / 100) P_total_lost = P_total * (P_loss / 100) K_total_lost = K_total * (K_loss / 100) Mg_total_lost = Mg_total * (Mg_loss / 100) Ca_total_lost = Ca_total * (Ca_loss / 100) N_total = N_total - N_total_lost N_amm = N_amm - N_total_lost # assume first N losses are ammonia for i in range(0, len(N_amm)): if N_amm[i] < 0: N_amm[i] = 0 P_total = P_total - P_total_lost K_total = K_total - K_total_lost Mg_total = Mg_total - Mg_total_lost Ca_total = Ca_total - Ca_total_lost energy = energy * ((100 - C_loss) / 100) # emissions transport_distance, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.transport_distance_tanker_truck, correlation_distributions, correlation_parameters, n_samples) emissions_factor, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.transport_emissions_factor_tanker_truck, correlation_distributions, correlation_parameters, n_samples) truck_emissions = (mass / 1000) * transport_distance * emissions_factor tech_operating_emissions[:, 2: 3] = tech_operating_emissions[:, 2: 3] + truck_emissions # cost: pit emptying is a future cost, to be annualized and normalized per capita capacity = np.array([ parameters.truck_emptying_capacity_1.expected, parameters.truck_emptying_capacity_2.expected, parameters.truck_emptying_capacity_3.expected, parameters.truck_emptying_capacity_4.expected ]).reshape(1, -1) base_price = np.array([ parameters.truck_emptying_cost_1.expected, parameters.truck_emptying_cost_2.expected, parameters.truck_emptying_cost_3.expected, parameters.truck_emptying_cost_4.expected ]).reshape(1, -1) add_fee_percentage, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.truck_emptying_add_fee_percentage, correlation_distributions, correlation_parameters, n_samples) emptying_price = ( np.repeat(base_price, n_samples, axis=0) * (1 + np.repeat(add_fee_percentage / 100, np.size(base_price), axis=1))) truck_capacity = np.repeat(capacity, n_samples, axis=0) ln_capacity = np.log(truck_capacity) ln_price = np.log(emptying_price) a = np.full((n_samples, 1), np.nan) b = np.full((n_samples, 1), np.nan) R2 = np.full((n_samples, 1), np.nan) for i in range(0, n_samples): model = LinearRegression().fit(ln_capacity[i, :].reshape(-1, 1), ln_price[i, :].reshape(-1, 1)) a[i] = np.exp(model.intercept_) b[i] = model.coef_ R2[i] = model.score(ln_capacity[i, :].reshape(-1, 1), ln_price[i, :].reshape(-1, 1)) cost_per_trip = a * ( (mass * number_users * previous_storage_time / 1000)**b) annualized_emptying_cost = ( cost_per_trip / number_users / exchange_rate) * (discount_rate / (( (1 + discount_rate)**previous_storage_time) - 1)) operating_cost[:, 2:3] = operating_cost[:, 2:3] + annualized_emptying_cost # return outputs to output matrix outputs[:, 0:9] = np.concatenate( (mass, mass_dry, N_total, P_total, K_total, Mg_total, Ca_total, energy, N_amm), 1) return outputs, tech_operating_emissions, operating_cost, correlation_distributions, correlation_parameters
def main(input_excel_name, excreta_inputs, urine_inputs, feces_inputs, tech_operating_emissions, operating_cost, correlation_distributions, correlation_parameters, n_samples, rate_constant, maximum_methane_emission, CH4_GWP, N2O_GWP, exchange_rate, discount_rate, number_users, previous_storage_time): # import module parameters from input spreadsheet parameters = pd.DataFrame.transpose( pd.read_excel(input_excel_name, sheet_name='conveyance').set_index('parameters')) # define the module(s) excreta_module = parameters.mixed_excreta_module.expected urine_module = parameters.urine_module.expected feces_module = parameters.feces_module.expected excreta_outputs = np.full(np.shape(excreta_inputs), np.nan) feces_outputs = np.full(np.shape(feces_inputs), np.nan) urine_outputs = np.full(np.shape(urine_inputs), np.nan) if (type(excreta_module) is float) and (type(urine_module) is float) and ( type(feces_module) is float): # if no modules specified, pass through (inputs = outputs) if np.isnan(excreta_module) and np.isnan(urine_module) and np.isnan( feces_module): excreta_outputs = excreta_inputs urine_outputs = urine_inputs feces_outputs = feces_inputs # other numerical inputs are not valid elif (not np.isnan(excreta_module)): raise ValueError( 'The conveyance module specified for excreta is not valid.') elif (not np.isnan(urine_module)): raise ValueError( 'The conveyance module specified for urine is not valid.') elif (not np.isnan(feces_module)): raise ValueError( 'The conveyance module specified for feces is not valid.') # otherwise, are both mixed and split stream options entered? elif (type(excreta_module) is str) and ((type(urine_module) is str) or (type(feces_module) is str)): raise ValueError( 'Modules for both the mixed and separated cases should not be evaluated simultaneously.' ) # otherwise, check mixed stream options first if type(excreta_module) is str: # tanker truck module if excreta_module == 'tanker_truck': (excreta_outputs, tech_operating_emissions, operating_cost, correlation_distributions, correlation_parameters) = tanker_truck( excreta_inputs, tech_operating_emissions, operating_cost, parameters, correlation_distributions, correlation_parameters, n_samples, rate_constant, maximum_methane_emission, CH4_GWP, N2O_GWP, exchange_rate, discount_rate, number_users, previous_storage_time) # if the excreta module input is not supported/valid else: raise ValueError( 'The conveyance module specified for excreta is not valid.') # separated streams if (type(urine_module) is str): # container based module if urine_module == 'handcart_and_truck': (urine_outputs, tech_operating_emissions, operating_cost, correlation_distributions, correlation_parameters) = handcart_and_truck( urine_inputs, tech_operating_emissions, operating_cost, parameters, correlation_distributions, correlation_parameters, n_samples, rate_constant, maximum_methane_emission, CH4_GWP, N2O_GWP, exchange_rate, discount_rate, number_users, previous_storage_time) # if the urine module input is not supported/valid else: raise ValueError( 'The conveyance module specified for urine is not valid.') if (type(feces_module) is str): # container based module if feces_module == 'handcart_and_truck': (feces_outputs, tech_operating_emissions, operating_cost, correlation_distributions, correlation_parameters) = handcart_and_truck( feces_inputs, tech_operating_emissions, operating_cost, parameters, correlation_distributions, correlation_parameters, n_samples, rate_constant, maximum_methane_emission, CH4_GWP, N2O_GWP, exchange_rate, discount_rate, number_users, previous_storage_time) # if the feces module input is not supported/valid else: raise ValueError( 'The conveyance module specified for feces is not valid.') if (urine_module == 'handcart_and_truck') or (feces_module == 'handcart_and_truck'): # add cost for CBS emptying to cover both urine and feces collection emptying_cost_CBS, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.emptying_cost_CBS_handcart, correlation_distributions, correlation_parameters, n_samples) emptying_cost_annualized = emptying_cost_CBS * (discount_rate / ( (1 + discount_rate)**(1 / 365) - 1)) # emptying_cost_annualized = emptying_cost_CBS * 365 operating_cost[:, 2:3] = operating_cost[:, 2:3] + emptying_cost_annualized return excreta_outputs, urine_outputs, feces_outputs, tech_operating_emissions, operating_cost, correlation_distributions, correlation_parameters
def handcart_and_truck(inputs, tech_operating_emissions, operating_cost, parameters, correlation_distributions, correlation_parameters, n_samples, rate_constant, maximum_methane_emission, CH4_GWP, N2O_GWP, exchange_rate, discount_rate, number_users, previous_storage_time): # mass and nutrients are recovered; this also maintains extra outputs outputs = copy.deepcopy(inputs) mass = np.reshape(inputs[:, 0], (-1, 1)) mass_dry = np.reshape(inputs[:, 1], (-1, 1)) N_total = np.reshape(inputs[:, 2], (-1, 1)) P_total = np.reshape(inputs[:, 3], (-1, 1)) K_total = np.reshape(inputs[:, 4], (-1, 1)) Mg_total = np.reshape(inputs[:, 5], (-1, 1)) Ca_total = np.reshape(inputs[:, 6], (-1, 1)) energy = np.reshape(inputs[:, 7], (-1, 1)) N_amm = np.reshape(inputs[:, 8], (-1, 1)) # nutrient losses during conveyance if parameters.losses_handcart_and_truck.expected == 'yes': N_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N_loss_handcart_and_truck, correlation_distributions, correlation_parameters, n_samples) P_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.P_loss_handcart_and_truck, correlation_distributions, correlation_parameters, n_samples) K_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.K_loss_handcart_and_truck, correlation_distributions, correlation_parameters, n_samples) Mg_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.Mg_loss_handcart_and_truck, correlation_distributions, correlation_parameters, n_samples) Ca_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.Ca_loss_handcart_and_truck, correlation_distributions, correlation_parameters, n_samples) C_loss, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.C_loss_handcart_and_truck, correlation_distributions, correlation_parameters, n_samples) else: N_loss = 0 P_loss = 0 K_loss = 0 Mg_loss = 0 Ca_loss = 0 C_loss = 0 # compute remaining nutrients after transfer losses N_total_lost = N_total * (N_loss / 100) P_total_lost = P_total * (P_loss / 100) K_total_lost = K_total * (K_loss / 100) Mg_total_lost = Mg_total * (Mg_loss / 100) Ca_total_lost = Ca_total * (Ca_loss / 100) N_total = N_total - N_total_lost N_amm = N_amm - N_total_lost # assume first N losses are ammonia for i in range(0, len(N_amm)): if N_amm[i] < 0: N_amm[i] = 0 P_total = P_total - P_total_lost K_total = K_total - K_total_lost Mg_total = Mg_total - Mg_total_lost Ca_total = Ca_total - Ca_total_lost energy = energy * ((100 - C_loss) / 100) # emissions transport_distance, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.transport_distance_CBS_truck, correlation_distributions, correlation_parameters, n_samples) emissions_factor, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.transport_emissions_factor_CBS_truck, correlation_distributions, correlation_parameters, n_samples) truck_emissions = (mass / 1000) * transport_distance * emissions_factor tech_operating_emissions[:, 2: 3] = tech_operating_emissions[:, 2: 3] + truck_emissions # cost: pit emptying is a future cost, to be annualized and normalized per capita truck_cost_UGX, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.transport_cost_CBS_truck, correlation_distributions, correlation_parameters, n_samples) annualized_truck_cost = ((truck_cost_UGX) / exchange_rate) * ( mass * previous_storage_time / 1000) * (discount_rate / (( (1 + discount_rate)**previous_storage_time) - 1)) # annualized_truck_cost = (truck_cost_UGX/exchange_rate)*(mass/1000) operating_cost[:, 2:3] = operating_cost[:, 2:3] + annualized_truck_cost # return outputs to output matrix outputs[:, 0:9] = np.concatenate( (mass, mass_dry, N_total, P_total, K_total, Mg_total, Ca_total, energy, N_amm), 1) return outputs, tech_operating_emissions, operating_cost, correlation_distributions, correlation_parameters
def main(excreta_inputs, urine_inputs, feces_inputs, direct_emissions, correlation_distributions, correlation_parameters, n_samples, rate_constant, maximum_methane_emission, CH4_GWP, N2O_GWP, number_users): # import module parameters from input spreadsheet parameters = pd.DataFrame.transpose( pd.read_excel( 'Bwaise_sanitation_inputs.xlsx', sheet_name='decentralized_storage').set_index('parameters')) # define the module(s) excreta_module = parameters.mixed_excreta_module.expected urine_module = parameters.urine_module.expected feces_module = parameters.feces_module.expected if (type(excreta_module) is float) and (type(urine_module) is float) and ( type(feces_module) is float): # if no modules specified, pass through (inputs = outputs) if np.isnan(excreta_module) and np.isnan(urine_module) and np.isnan( feces_module): excreta_outputs = excreta_inputs urine_outputs = urine_inputs feces_outputs = feces_inputs # other numerical inputs are not valid elif (not np.isnan(excreta_module)): raise ValueError( 'The decentralized collection and storage module specified for excreta is not valid.' ) elif (not np.isnan(urine_module)): raise ValueError( 'The decentralized collection and storage module specified for urine is not valid.' ) elif (not np.isnan(feces_module)): raise ValueError( 'The decentralized collection and storage module specified for feces is not valid.' ) # otherwise, are both mixed and split stream options entered? elif (type(excreta_module) is str) and ((type(urine_module) is str) or (type(feces_module) is str)): raise ValueError( 'Modules for both the mixed and separated cases should not be evaluated simultaneously.' ) # otherwise, check mixed stream options first elif type(excreta_module) is str: # single pit module if excreta_module == 'single_pit': (excreta_outputs, direct_emissions, correlation_distributions, correlation_parameters, previous_storage_time) = single_pit( excreta_inputs, direct_emissions, parameters, correlation_distributions, correlation_parameters, n_samples, rate_constant, maximum_methane_emission, CH4_GWP, N2O_GWP, number_users) # if the excreta module input is not supported/valid else: raise ValueError( 'The decentralized collection and storage module specified for excreta is not valid.' ) # no separate urine/feces streams urine_outputs = np.full(np.shape(urine_inputs), np.nan) feces_outputs = np.full(np.shape(feces_inputs), np.nan) elif (type(urine_module) is str) and (type(feces_module) is str): collection_period, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.CBS_collection_period, correlation_distributions, correlation_parameters, n_samples) # storage tank module if urine_module == 'storage_tank': (urine_outputs, direct_emissions, correlation_distributions, correlation_parameters, previous_storage_time) = storage_tank( urine_inputs, direct_emissions, parameters, correlation_distributions, correlation_parameters, n_samples, rate_constant, maximum_methane_emission, CH4_GWP, N2O_GWP, number_users, collection_period) # if the urine module input is not supported/valid else: raise ValueError( 'The decentralized collection and storage module specified for urine is not valid.' ) # dehydration vault module if feces_module == 'dehydration_vault': (feces_outputs, direct_emissions, correlation_distributions, correlation_parameters, previous_storage_time) = dehydration_vault( feces_inputs, direct_emissions, parameters, correlation_distributions, correlation_parameters, n_samples, rate_constant, maximum_methane_emission, CH4_GWP, N2O_GWP, number_users, collection_period) # if the feces module input is not supported/valid else: raise ValueError( 'The decentralized collection and storage module specified for feces is not valid.' ) # no mixed excreta stream excreta_outputs = np.full(np.shape(excreta_inputs), np.nan) elif (type(urine_module) is str) or (type(feces_module) is str): raise ValueError( 'For systems with separated urine and fecal streams, both urine and feces modules must be specified for decentralized collection and storage.' ) else: raise ValueError( 'The specified decentralized collection and storage modules are not valid.' ) return excreta_outputs, urine_outputs, feces_outputs, direct_emissions, correlation_distributions, correlation_parameters, previous_storage_time
def dehydration_vault(feces_inputs, direct_emissions, parameters, correlation_distributions, correlation_parameters, n_samples, rate_constant, maximum_methane_emission, CH4_GWP, N2O_GWP, number_users, collection_period): # separate out input variables from concatenated arrays feces = np.reshape(feces_inputs[:, 0], (-1, 1)) feces_dry = np.reshape(feces_inputs[:, 1], (-1, 1)) N_total = np.reshape(feces_inputs[:, 2], (-1, 1)) P_total = np.reshape(feces_inputs[:, 3], (-1, 1)) K_total = np.reshape(feces_inputs[:, 4], (-1, 1)) Mg_total = np.reshape(feces_inputs[:, 5], (-1, 1)) Ca_total = np.reshape(feces_inputs[:, 6], (-1, 1)) energy_total = np.reshape(feces_inputs[:, 7], (-1, 1)) N_ammonia = np.reshape(feces_inputs[:, 8], (-1, 1)) # 1. emissions through degradation # convert storage time from days to years storage_time = collection_period / 365 # initial moisture content MC_initial = (1 - feces_dry / feces) * 100 # do air emissions occur? if parameters.air_emissions_vault.expected == 'yes': MCF_vault, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.MCF_vault, correlation_distributions, correlation_parameters, n_samples) N2O_EF_vault, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N2O_EF_vault, correlation_distributions, correlation_parameters, n_samples) OD_max_removal_storage, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.OD_max_removal_storage, correlation_distributions, correlation_parameters, n_samples) # carbon (kg COD/yr; assume 14 kJ/g COD in wastewater) COD_total = (energy_total / 14 / 1000) COD_degrade = COD_total * (OD_max_removal_storage / 100) COD_after = (COD_degrade / (rate_constant * storage_time)) * ( np.exp(-rate_constant * storage_time) - np.exp(-rate_constant * (storage_time + storage_time))) COD_loss = COD_degrade - COD_after COD_reduction = COD_loss / COD_total CH4_emission = COD_loss * (MCF_vault / 100) * maximum_methane_emission CH4eq = CH4_emission * CH4_GWP COD_total = COD_total - COD_loss energy_total = COD_total * 14 * 1000 # nitrogen (kg N/yr; N2O expressed as kg N2O/yr) N_max_denit, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N_max_denitrification_storage, correlation_distributions, correlation_parameters, n_samples) N_denit = N_total * (N_max_denit / 100) N_after = (N_denit / (rate_constant * storage_time)) * ( np.exp(-rate_constant * storage_time) - np.exp(-rate_constant * (storage_time + storage_time))) N_loss = N_denit - N_after N2O_emission = N_total * (N_loss / N_denit) * (N2O_EF_vault / 100) * (44 / 28) N2Oeq = N2O_emission * N2O_GWP N_total = N_total - N_loss N_ammonia = N_ammonia - N_loss for i in range(0, len(N_ammonia)): if N_ammonia[i] < 0: N_ammonia[i] = 0 # solids loss (based on COD loss) feces = feces - feces_dry * COD_reduction feces_dry = feces_dry - feces_dry * COD_reduction else: CH4eq = np.full((n_samples, 1), 0) N2Oeq = np.full((n_samples, 1), 0) # water losses (evaporation/drying) if desiccant added if parameters.desiccant_added.expected == 'yes': MC_minimum, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.minimum_moisture_content, correlation_distributions, correlation_parameters, n_samples) decay_rate, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.exponential_MC_decay, correlation_distributions, correlation_parameters, n_samples) # express time in days to match decay rate time_days = storage_time * 365 # calculate final MC as average of each addition over time MC_final = ((MC_initial - MC_minimum) / (decay_rate * time_days)) * ( 1 - np.exp(-decay_rate * time_days)) + MC_minimum # calculate final total mass of feces feces = feces_dry / (1 - (MC_final / 100)) # dehydration vault required volume (m3): assume feces density ~ 1000 kg/m3 vault_volume = (feces * storage_time * number_users) / 1000 # non-ideal emptying (some latrines are emptied inappropriately, discharged directly to drainage channels or aquatic environments) if parameters.ideal_emptying.expected == 'no': # parameters appropriate_emptying, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.appropriate_emptying, correlation_distributions, correlation_parameters, n_samples) MCF_aquatic_discharge, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.MCF_aquatic_discharge, correlation_distributions, correlation_parameters, n_samples) N2O_EF_aquatic_discharge, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N2O_EF_aquatic_discharge, correlation_distributions, correlation_parameters, n_samples) # carbon CH4_emission = COD_total * (1 - (appropriate_emptying / 100)) * ( OD_max_removal_storage / 100) * (MCF_aquatic_discharge / 100) * maximum_methane_emission CH4eq = CH4eq + CH4_emission * CH4_GWP COD_total = COD_total * (appropriate_emptying / 100) energy_total = COD_total * 14 * 1000 # nitrogen N2O_emission = N_total * (1 - (appropriate_emptying / 100)) * ( N2O_EF_aquatic_discharge / 100) * (44 / 28) N2Oeq = N2Oeq + N2O_emission * N2O_GWP N_total = N_total * (appropriate_emptying / 100) # others N_ammonia = N_ammonia * (appropriate_emptying / 100) P_total = P_total * (appropriate_emptying / 100) K_total = K_total * (appropriate_emptying / 100) Mg_total = Mg_total * (appropriate_emptying / 100) Ca_total = Ca_total * (appropriate_emptying / 100) feces = feces * (appropriate_emptying / 100) feces_dry = feces_dry * (appropriate_emptying / 100) direct_emissions[:, 1:2] = direct_emissions[:, 1:2] + CH4eq + N2Oeq # concatenate outputs feces_outputs = np.concatenate( (feces, feces_dry, N_total, P_total, K_total, Mg_total, Ca_total, energy_total, N_ammonia, vault_volume), 1) previous_storage_time = storage_time return feces_outputs, direct_emissions, correlation_distributions, correlation_parameters, previous_storage_time
def storage_tank(urine_inputs, direct_emissions, parameters, correlation_distributions, correlation_parameters, n_samples, rate_constant, maximum_methane_emission, CH4_GWP, N2O_GWP, number_users, collection_period): # separate out input variables from concatenated arrays urine = np.reshape(urine_inputs[:, 0], (-1, 1)) urine_dry = np.reshape(urine_inputs[:, 1], (-1, 1)) N_total = np.reshape(urine_inputs[:, 2], (-1, 1)) P_total = np.reshape(urine_inputs[:, 3], (-1, 1)) K_total = np.reshape(urine_inputs[:, 4], (-1, 1)) Mg_total = np.reshape(urine_inputs[:, 5], (-1, 1)) Ca_total = np.reshape(urine_inputs[:, 6], (-1, 1)) energy_total = np.reshape(urine_inputs[:, 7], (-1, 1)) N_ammonia = np.reshape(urine_inputs[:, 8], (-1, 1)) # 1. N losses due to ammonia volatilization (kg N/yr) N_volatilization, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N_urine_volatilization, correlation_distributions, correlation_parameters, n_samples) # calculate mass of N volatilized (kg N/yr) N_volatilized = N_total * (N_volatilization / 100) # remaining total N and ammonia (kg N/yr) N_total = N_total - N_volatilized N_ammonia = N_ammonia - N_volatilized for i in range(0, len(N_ammonia)): if N_ammonia[i] < 0: N_ammonia[i] = 0 # remaining dry matter and total mass urine_dry = urine_dry - (N_volatilized * 17 / 14) urine = urine - (N_volatilized * 17 / 14) # 2. N and P losses due to precipitation of struvite and HAP (assume as much Mg and Ca consumed as possible) if parameters.precipitation_losses.expected == 'yes': # initialize matrices to hold precipitate quantities struvite = np.full(np.shape(P_total), np.nan) HAP = np.full(np.shape(P_total), np.nan) # molar concentrations amm_M = ((N_ammonia / urine) * 1000) / 14.01 P_M = ((P_total / urine) * 1000) / 30.97 Mg_M = ((Mg_total / urine) * 1000) / 24.31 # conditional Ksp pKsp, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.struvite_cond_pKsp, correlation_distributions, correlation_parameters, n_samples) Ksp = 10.0**(-pKsp) # use cond Ksp to calculate equilibrium conditions for i in range(0, len(P_total)): # coefficients of cubic equation (Ksp = (initial N - struvite)(initial P - struvite)(initial Mg - struvite)) coeff = [ 1, -(Mg_M[i] + amm_M[i] + P_M[i]), (Mg_M[i] * amm_M[i] + amm_M[i] * P_M[i] + Mg_M[i] * P_M[i]), (Ksp[i] - Mg_M[i] * amm_M[i] * P_M[i]) ] # calculate roots of cubic r = np.roots(coeff) # identify true struvite production for j in range(0, len(r)): if np.min([Mg_M[i], amm_M[i], P_M[i]]) > r[j]: struvite[i] = (r[j] * 245.41 / 1000) * urine[i] if struvite[i] < 0: struvite[i] = 0 # calculate nutrients in unrecoverable struvite (scaling; sludge is recoverable) precipitate_sludge, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.precipitate_sludge, correlation_distributions, correlation_parameters, n_samples) struvite = struvite * ((100 - precipitate_sludge) / 100) P_struvite = struvite * 30.97 / 245.41 N_struvite = struvite * 14 / 245.41 Mg_struvite = struvite * 24.31 / 245.41 # remaining after precipitation (and accounting for sludge fraction, which can still be recovered) N_total = N_total - N_struvite N_ammonia = N_ammonia - N_struvite P_total = P_total - P_struvite Mg_total = Mg_total - Mg_struvite for i in range(0, len(P_total)): # HAP losses (precipitates second according to Udert et al., 2003) - expect all precipitates, due to very high pKsp (57.5) # compare molar ratios to determine which element is completely consumed (3 P : 5 Ca) if (P_total[i] / (3 * 30.97)) > (Ca_total[i] / (5 * 40.08)): # all Ca consumed HAP[i] = Ca_total[i] * 502.31 / (5 * 40.08) else: # all P consumed HAP[i] = P_total[i] * 502.31 / (3 * 30.97) # calculate precipitated nutrients in HAP (in scale; sludge is recoverable) HAP = HAP * ((100 - precipitate_sludge) / 100) P_HAP = HAP * (3 * 30.97) / 502.31 Ca_HAP = HAP * (5 * 40.08) / 502.31 # total precipitated precipitate = struvite + HAP # remaining after precipitation P_total = P_total - P_HAP Ca_total = Ca_total - Ca_HAP urine = urine - precipitate # do not include complexed water or hydroxide ions as coming from solids urine_dry = urine_dry - (struvite * 137.29 / 245.41) - (HAP * 485.3 / 502.31) # correct for any rounding errors that create negative numbers N_total[N_total < 0] = 0 P_total[P_total < 0] = 0 Mg_total[Mg_total < 0] = 0 Ca_total[Ca_total < 0] = 0 N_ammonia[N_ammonia < 0] = 0 else: precipitate = 0 # 3. pathogen inactivation (using Fidjeland et al., 2015 model for Ascaris egg inactivation through ammonia) if parameters.in_situ_treatment.expected == 'yes': # define parameters log_inactivation, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.desired_pathogen_inactivation, correlation_distributions, correlation_parameters, n_samples) safety_factor, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.safety_factor, correlation_distributions, correlation_parameters, n_samples) temperature, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.temperature, correlation_distributions, correlation_parameters, n_samples) pH, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.stored_urine_pH, correlation_distributions, correlation_parameters, n_samples) # define total ammonia concentration (mM N) TAN_conc = (N_ammonia * 1000000 / 14) / urine # define dry matter content (%) DM = (urine_dry / urine) * 100 # calculate ammonia pKa pKa = 0.09018 + (2729.92 / (273.15 + temperature)) # calculate fraction of total ammonia present as free ammonia (using equation from Emerson et al., 1975) f_NH3_Emerson = 1 / (10**(pKa - pH) + 1) # convert Emerson fraction to Pitzer fraction as required by Fidjeland et al. model alpha = 0.82 - 0.011 * np.sqrt(TAN_conc + 1700 * (DM / 100)) beta = 1.17 + 0.02 * np.sqrt(TAN_conc + 1100 * (DM / 100)) f_NH3_Pitzer = f_NH3_Emerson * (alpha + ((1 - alpha) * (f_NH3_Emerson**beta))) # calculate free ammonia concentration NH3_conc = TAN_conc * f_NH3_Pitzer # calculate time (in days) to reach desired inactivation level (Fidjeland et al., 2015) treatment_time = (((3.2 + log_inactivation) / (10**(-3.7 + 0.062 * temperature) * (NH3_conc**0.7))) * 1.14 * safety_factor) # total required treatment volume (L) treatment_volume = treatment_time * (urine * number_users / 365) elif parameters.in_situ_treatment.expected == 'no': treatment_time = np.full(np.shape(urine), np.nan) treatment_volume = np.full(np.shape(urine), np.nan) # 4. storage tank filling time tank_volume, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.tank_volume, correlation_distributions, correlation_parameters, n_samples) # calculate filling time (days), assuming urine density is approximately 1 kg/L and including precipitates filling_time = (tank_volume / ((urine + precipitate) * number_users)) * 365 CH4eq = np.full([n_samples, 1], 0) N2Oeq = np.full([n_samples, 1], 0) # non-ideal emptying (some latrines are emptied inappropriately, discharged directly to drainage channels or aquatic environments) if parameters.ideal_emptying.expected == 'no': # parameters OD_max_removal_storage, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.OD_max_removal_storage, correlation_distributions, correlation_parameters, n_samples) appropriate_emptying, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.appropriate_emptying, correlation_distributions, correlation_parameters, n_samples) MCF_aquatic_discharge, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.MCF_aquatic_discharge, correlation_distributions, correlation_parameters, n_samples) N2O_EF_aquatic_discharge, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N2O_EF_aquatic_discharge, correlation_distributions, correlation_parameters, n_samples) # carbon COD_total = (energy_total / 14 / 1000) CH4_emission = COD_total * (1 - (appropriate_emptying / 100)) * ( OD_max_removal_storage / 100) * (MCF_aquatic_discharge / 100) * maximum_methane_emission CH4eq = CH4eq + CH4_emission * CH4_GWP COD_total = COD_total * (appropriate_emptying / 100) energy_total = COD_total * 14 * 1000 # nitrogen N2O_emission = N_total * (1 - (appropriate_emptying / 100)) * ( N2O_EF_aquatic_discharge / 100) * (44 / 28) N2Oeq = N2Oeq + N2O_emission * N2O_GWP N_total = N_total * (appropriate_emptying / 100) # others N_ammonia = N_ammonia * (appropriate_emptying / 100) P_total = P_total * (appropriate_emptying / 100) K_total = K_total * (appropriate_emptying / 100) Mg_total = Mg_total * (appropriate_emptying / 100) Ca_total = Ca_total * (appropriate_emptying / 100) urine = urine * (appropriate_emptying / 100) urine_dry = urine_dry * (appropriate_emptying / 100) direct_emissions[:, 1:2] = direct_emissions[:, 1:2] + CH4eq + N2Oeq # concatenate outputs urine_outputs = np.concatenate( (urine, urine_dry, N_total, P_total, K_total, Mg_total, Ca_total, energy_total, N_ammonia, filling_time, treatment_time, treatment_volume), 1) previous_storage_time = collection_period / 365 return urine_outputs, direct_emissions, correlation_distributions, correlation_parameters, previous_storage_time
def single_pit(excreta_inputs, direct_emissions, parameters, correlation_distributions, correlation_parameters, n_samples, rate_constant, maximum_methane_emission, CH4_GWP, N2O_GWP, number_users): # separate out input variables from concatenated arrays excreta = np.reshape(excreta_inputs[:, 0], (-1, 1)) excreta_dry = np.reshape(excreta_inputs[:, 1], (-1, 1)) N_total = np.reshape(excreta_inputs[:, 2], (-1, 1)) P_total = np.reshape(excreta_inputs[:, 3], (-1, 1)) K_total = np.reshape(excreta_inputs[:, 4], (-1, 1)) Mg_total = np.reshape(excreta_inputs[:, 5], (-1, 1)) Ca_total = np.reshape(excreta_inputs[:, 6], (-1, 1)) energy_total = np.reshape(excreta_inputs[:, 7], (-1, 1)) N_ammonia = np.reshape(excreta_inputs[:, 8], (-1, 1)) # 1. Losses # does infiltration occur? if parameters.infiltration.expected == 'yes': # define parameters N_leaching, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N_leaching, correlation_distributions, correlation_parameters, n_samples) P_leaching, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.P_leaching, correlation_distributions, correlation_parameters, n_samples) K_leaching, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.K_leaching, correlation_distributions, correlation_parameters, n_samples) elif parameters.infiltration.expected == 'no': N_leaching = 0 P_leaching = 0 K_leaching = 0 # compute losses N_infiltrated = N_total * (N_leaching / 100) P_infiltrated = P_total * (P_leaching / 100) K_infiltrated = K_total * (K_leaching / 100) N_total = N_total - N_infiltrated N_ammonia = N_ammonia - N_infiltrated for i in range(0, len(N_ammonia)): if N_ammonia[i] < 0: N_ammonia[i] = 0 P_total = P_total - P_infiltrated K_total = K_total - K_infiltrated # do air emissions occur? pit_emptying_period, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.pit_emptying_period, correlation_distributions, correlation_parameters, n_samples) if parameters.air_emissions_pit.expected == 'yes': # parameters N_volatilization, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N_pit_volatilization, correlation_distributions, correlation_parameters, n_samples) N_vol = N_total * (N_volatilization) / 100 N_total = N_total - N_vol N_ammonia = N_ammonia - N_vol for i in range(0, len(N_ammonia)): if N_ammonia[i] < 0: N_ammonia[i] = 0 if parameters.pit_above_water_table.expected == 'yes': if parameters.shared.expected == 'no': MCF, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.MCF_single_above_water, correlation_distributions, correlation_parameters, n_samples) N2O_EF, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N2O_EF_single_above_water, correlation_distributions, correlation_parameters, n_samples) elif parameters.shared.expected == 'yes': MCF, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.MCF_communal_above_water, correlation_distributions, correlation_parameters, n_samples) N2O_EF, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N2O_EF_communal_above_water, correlation_distributions, correlation_parameters, n_samples) elif parameters.pit_above_water_table.expected == 'no': MCF, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.MCF_below_water, correlation_distributions, correlation_parameters, n_samples) N2O_EF, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N2O_EF_below_water, correlation_distributions, correlation_parameters, n_samples) OD_max_removal_storage, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.OD_max_removal_storage, correlation_distributions, correlation_parameters, n_samples) # calculations # carbon (kg COD/yr; assume 14 kJ/g COD in wastewater) COD_total = (energy_total / 14 / 1000) COD_degrade = COD_total * (OD_max_removal_storage / 100) COD_after = (COD_degrade / (rate_constant * pit_emptying_period)) * ( 1 - np.exp(-rate_constant * pit_emptying_period)) COD_loss = COD_degrade - COD_after CH4_emission = COD_loss * (MCF / 100) * maximum_methane_emission CH4eq = CH4_emission * CH4_GWP COD_reduction = COD_loss / COD_total COD_total = COD_total - COD_loss energy_total = COD_total * 14 * 1000 # nitrogen (kg N/yr; N2O expressed as kg N2O/yr) N_max_denit, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N_max_denitrification_storage, correlation_distributions, correlation_parameters, n_samples) N_denit = N_total * (N_max_denit / 100) N_after = (N_denit / (rate_constant * pit_emptying_period)) * ( 1 - np.exp(-rate_constant * pit_emptying_period)) N_loss = N_denit - N_after N2O_emission = N_total * (N_loss / N_denit) * (N2O_EF / 100) * (44 / 28) for i in range(0, len(N2O_emission)): if N2O_emission[i] > N_loss[i] * (44 / 28): N2O_emission[i] = N_loss[i] * (44 / 28) N2Oeq = N2O_emission * N2O_GWP N_total = N_total - N_loss N_ammonia = N_ammonia - N_loss for i in range(0, len(N_ammonia)): if N_ammonia[i] < 0: N_ammonia[i] = 0 # solids loss (based on COD loss) excreta = excreta - excreta_dry * COD_reduction excreta_dry = excreta_dry - (excreta_dry * COD_reduction) else: CH4eq = np.full((n_samples, 1), 0) N2Oeq = np.full((n_samples, 1), 0) # total accumulation (kg/yr) sludge_accumulation_rate, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.sludge_accumulation_rate, correlation_distributions, correlation_parameters, n_samples) total_accumulation = sludge_accumulation_rate * number_users excreta_out = copy.deepcopy(excreta) for i in range(0, len(total_accumulation)): # if total accumulation is between total solids and total influent mass if (excreta_dry[i] * number_users[i] < total_accumulation[i]) and ( total_accumulation[i] < excreta_out[i] * number_users[i]): excreta_out[i] = total_accumulation[i] / number_users[i] # if total solids is greater than total accumulation, assume all water has drained elif (excreta_dry[i] * number_users[i] > total_accumulation[i]): excreta_out[i] = excreta_dry[i] # otherwise (total influent mass < expected accumulation), then do nothing (no drainage) # 2. Pit filling time # define pit dimensions pit_depth, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.pit_depth, correlation_distributions, correlation_parameters, n_samples) pit_area, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.pit_area, correlation_distributions, correlation_parameters, n_samples) # calculate pit volume (m3) pit_volume = pit_depth * pit_area # calculate filling time (years), assuming density of contents is approximately 1000 kg/m3 filling_time = pit_volume / (excreta_out * number_users / 1000) # non-ideal emptying (some latrines are emptied inappropriately, discharged directly to drainage channels or aquatic environments) if parameters.ideal_emptying.expected == 'no': # parameters appropriate_emptying, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.appropriate_emptying, correlation_distributions, correlation_parameters, n_samples) MCF_aquatic_discharge, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.MCF_aquatic_discharge, correlation_distributions, correlation_parameters, n_samples) N2O_EF_aquatic_discharge, correlation_distributions, correlation_parameters = lhs.lhs_distribution( parameters.N2O_EF_aquatic_discharge, correlation_distributions, correlation_parameters, n_samples) # carbon CH4_emission = COD_total * (1 - (appropriate_emptying / 100)) * ( OD_max_removal_storage / 100) * (MCF_aquatic_discharge / 100) * maximum_methane_emission CH4eq = CH4eq + CH4_emission * CH4_GWP COD_total = COD_total * (appropriate_emptying / 100) energy_total = COD_total * 14 * 1000 # nitrogen N2O_emission = N_total * (1 - (appropriate_emptying / 100)) * ( N2O_EF_aquatic_discharge / 100) * (44 / 28) N2Oeq = N2Oeq + N2O_emission * N2O_GWP N_total = N_total * (appropriate_emptying / 100) # others N_ammonia = N_ammonia * (appropriate_emptying / 100) P_total = P_total * (appropriate_emptying / 100) K_total = K_total * (appropriate_emptying / 100) Mg_total = Mg_total * (appropriate_emptying / 100) Ca_total = Ca_total * (appropriate_emptying / 100) excreta_out = excreta_out * (appropriate_emptying / 100) excreta_dry = excreta_dry * (appropriate_emptying / 100) direct_emissions[:, 1:2] = direct_emissions[:, 1:2] + CH4eq + N2Oeq # concatenate outputs excreta_outputs = np.concatenate( (excreta_out, excreta_dry, N_total, P_total, K_total, Mg_total, Ca_total, energy_total, N_ammonia, filling_time), 1) previous_storage_time = pit_emptying_period return excreta_outputs, direct_emissions, correlation_distributions, correlation_parameters, previous_storage_time