Exemple #1
0
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
Exemple #2
0
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
Exemple #4
0
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
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
0
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
Exemple #8
0
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
Exemple #9
0
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
Exemple #10
0
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
Exemple #11
0
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