# coding=utf-8
#
# Copyright 2021-2022 Romain BESSEAU <romain.besseau@ec.europa.eu>
# Copyright 2022-2024 Alejandra CUE GONZALEZ <alejandra.cue_gonzalez@minesparis.psl.eu>
# Copyright 2022-2024 Benoît GSCHWIND <benoit.gschwind@minesparis.psl.eu>
# Copyright 2022-2024 MINES Paris
#
# This file is part of "parasol-lca" and you can used under the
# term of European Union Public Licence.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# European Union Public Licence for more details.
#
# Version: 22 April 2025
#
# Code authors: Romain BESSEAU, Benoît GSCHWIND, Alejandra CUE GONZALEZ
#

import lca_algebraic as agb
from lca_algebraic.base_utils import getActByCode
from lca_algebraic import unit_registry as u
agb.Settings.units_enabled = True

import brightway2 as bw
from bw2data.utils import get_activity
from bw2data.query import Filter

class ensure_activity:
    def __init__(self, name):
        self.name = name
    def __call__(self, func):
        def _ensure_activity(conf):
            ACTIVITY_NAME = f'{conf.prefix}{self.name}'
            act = agb.findActivity(ACTIVITY_NAME, db_name=conf.target_database, single=False)
            if isinstance(act, list):
                if len(act) == 0:
                    return func(ACTIVITY_NAME, conf)
                raise Exception(f"Error: Unexpected multiples activities {ACTIVITY_NAME}: {act}")
            return act
        return _ensure_activity

def get_acurate_activities(db_name, filters : dict):
    return [get_activity(key) for key in bw.Database(db_name).query(*[Filter(k, "==", v) for k, v in filters.items()])]

@ensure_activity("electricity")
def _ensure_electricity(ACTIVITY_NAME: str, conf):
    """Create the electricity dataset and related activities.
    Activities of the market and market group for electricity, medium voltage,
    are recovered from the ecoinvent database for France (FR), Europe (EU),
    United States (US), China (CN), and the global market (World).
    Activities related to the electricity production through photovoltaic (PV),
    nuclear (Nuclear), and coal (Coal) are also recovered.
    Finally, an activity with a fixed share of fossil to determine the
    CO2 content is defined (CO2_content)

    These activities are aggregated in a virtual "switch" activity,
    from which the desired electricity source for PV manufacuring can be chosen

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    # ## Electricity dataset

    # These variables save the technosphere activities related to the electricity markets for different regions, as well as general energy markets.

    ### Electricity mix
    elec_FR = agb.findActivity('market for electricity, medium voltage','FR', db_name=conf.technosphere)
    elec_EU = agb.findActivity('market group for electricity, medium voltage', 'ENTSO-E', db_name=conf.technosphere)
    elec_US = agb.findActivity('market group for electricity, medium voltage','US', db_name=conf.technosphere)
    elec_CN = agb.findActivity('market group for electricity, medium voltage','CN', db_name=conf.technosphere)
    elec_world = agb.findActivity('market group for electricity, medium voltage','GLO', db_name=conf.technosphere)
    elec_PV = agb.findActivity('electricity production, photovoltaic, 570kWp open ground installation, multi-Si','FR', db_name=conf.technosphere)
    elec_nuclear = agb.findActivity('electricity production, nuclear, pressure water reactor','FR', db_name=conf.technosphere)
    elec_coal = agb.findActivity('electricity production, hard coal','FR', db_name=conf.technosphere)

    # We declare a parameter to select the electricity mix to be used for the manufacturing of PV components.

    # ### Dataset with a fixed share of fossil to determine the CO2 content

    # A parameterized mix with only hydropower and coal power can also be used.
    # It is convenient as the carbon footprint of hydropower is very low and
    # the carbon footprint of coal power plant is close to 1 kgCO2eq/kWh.
    # If you want to consider an electricity dataset with a carbon footprint
    # of 300 gCO2eq/kWh, you can use this dataset with a ratio of 0.3 of coal power.

    act_kWh_hydro = agb.findActivity('electricity production, hydro, reservoir, alpine region','FR', db_name=conf.technosphere)
    act_kWh_charbon =  agb.findActivity('electricity production, hard coal','RoW', db_name=conf.technosphere)

    act = agb.newActivity(
        name=f'{conf.prefix}electricity for PV manufacturing CO2 content',
        db_name = conf.target_database,
        unit = "kWh",
        exchanges={
            act_kWh_charbon: conf.electricity_mix_CO2_content,
            act_kWh_hydro: 1-conf.electricity_mix_CO2_content
        }
    )
    act.setOutputAmount(1.0)

    # +
    act_kWh_CO2 = agb.findActivity(f'{conf.prefix}electricity for PV manufacturing CO2 content', db_name=conf.target_database)
    # -

    # The following is a virtual activity corresponding to switch beteween electricity mixes.
    # We assign those values to the Manufacturing_elrctricity_mix parameter.
    #
    # If necessary, more choices can be added.

    return agb.newSwitchAct(
        name=ACTIVITY_NAME,
        dbname = conf.target_database,
        paramDef = conf.manufacturing_electricity_mix,
        acts_dict = {
            'FR' : elec_FR,
            'EU' : elec_EU,
            'US' : elec_US,
            'CN' : elec_CN,
            'World' : elec_world,
            'PV' : elec_PV,
            'Nuclear' : elec_nuclear,
            'Coal' : elec_coal,
            'CO2_content' : act_kWh_CO2
        }
    )


@ensure_activity("PV mounting system, ground")
def _ensure_mounting_ground(ACTIVITY_NAME: str, conf):
    """Create the mounting system dataset and related activities needed for 1 m2 PV panel.
    Paramaterizes the ecoinvent photovoltaic mounting system production
    activity by including the parameters related to the total weight of the
    mounting system, the amount of aluminum, and the amount of wood in kg.
    It also updates the type of steel used for the mounting system.

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    #VALUES
    DENSITY__WOOD = 420.0 | (u.kg/(u.m**3))
    chromium_steel = 0.25 | u.kg
    concrete_volume = 0.000542|(u.m**3)
    SURFACE = 1.0|(u.m**2)
    
    # ## Mounting system
    # Mounting system (Aluminium and stainless steel based)
    ground_system = agb.findActivity('photovoltaic mounting system production, for 570kWp open ground module', db_name=conf.technosphere)

    # Markets for scrap alumuinium
    
    if conf.version in {'3.11'} : 
        scrap_alu = agb.findActivity('aluminium scrap, post-consumer, Recycled Content cut-off','GLO', db_name=conf.technosphere)
        scrap_steel = agb.findActivity('iron scrap, unsorted, Recycled Content cut-off','GLO', db_name=conf.technosphere)
    else:
       scrap_alu = agb.findActivity('market for scrap aluminium','Europe without Switzerland', db_name=conf.technosphere)
       scrap_steel = agb.findActivity('market for scrap steel','Europe without Switzerland', db_name=conf.technosphere) 

    # We add the activity related to wood to include wood as a potential material to be used in the mounting system.
    wood_act = agb.findActivity('market for sawnwood, softwood, dried (u=20%), planed','RER', db_name=conf.technosphere)

    # We copy this way to avoid accidental modifications of the original activity
    act2 = agb.copyActivity(
            activity = ground_system,
            code = ACTIVITY_NAME,
            db_name = conf.target_database)

    #Update the ground system activity (process) with exchanges that include the paramaters that we defined
    #Aluminum
    m_alu = conf.mounting_system_weight_alu
    # weight of materials in kg/(m**2). multiply per 1 m**2
    m_steel = (conf.mounting_system_weight_total - conf.mounting_system_weight_alu - conf.mounting_system_weight_wood)*SURFACE
    m_wood = conf.mounting_system_weight_wood / DENSITY__WOOD #420 kg/m3

    #Alu
    if conf.version in {'3.11'} : 
        act2.updateExchanges({"aluminium scrap, post-consumer*": -m_alu})
        act2.updateExchanges({"iron scrap, unsorted*": -m_steel})
    else : 
        act2.updateExchanges({"scrap aluminium*": None})
        act2.addExchanges({scrap_alu : -m_alu})
        act2.updateExchanges({"scrap steel*": None})
        act2.addExchanges({scrap_steel : -m_steel})
            
    act2.updateExchanges({"aluminium*": m_alu})
    act2.updateExchanges({"reinforcing steel*": m_steel - chromium_steel})#substract chromium steel
    act2.updateExchanges({"section bar rolling, steel*": m_steel})
    #Wood
    act2.addExchanges({wood_act:m_wood})

    #GCR
    act2.updateExchanges({"Transformation*": 1.0/conf.ground_coverage_ratio * (1.0-conf.roof_vs_ground_ratio)})
    #FIXME reflect on the roof_vs_ground paramater with the addition of a mounting structure switch
    # For a sensitivity analysis, statistical weight need to be given to each alternative
    # If not, it means they all have the same weight
    act2.updateExchanges({"Occupation*": 1.0/conf.ground_coverage_ratio * conf.power_plant_lifetime * (1.0-conf.roof_vs_ground_ratio)})
    #Concrete
    act2.updateExchanges({'concrete, normal strength':concrete_volume * (1.0-conf.roof_vs_ground_ratio)})

    return act2

#XXX Modular mounting system
# FIXME land
@ensure_activity("PV mounting system, floating, lake")
def _ensure_mounting_floating_lake(ACTIVITY_NAME: str, conf):
    """Creates the dataset and related activities for a floating on a lake PV mounting system.
    Paramaterizes the ecoinvent PV mounting system production
    activity by including the parameters related to the total weight of the
    mounting system, the amount of aluminum, and the amount of wood in kg.
    It also updates the type of steel used for the mounting system.

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity
    """
    # Values source: https://iea-pvps.org/wp-content/uploads/2024/07/IEA-PVPS-T12-29-2024-REPORT-Floating-PV-Carbon-Footprint2.pdf
    # Total weight materials = 1.43+43.5+2.15+45
    # steel, HDPE, aluminum, concrete
    concrete = 45.0 | u.kg
    HDPE = 11.4 | u.kg
    blow_m = 11.4 | u.kg
    steel_alloy = 0.38 | u.kg
    AlMg3 = 0.57 | u.kg
    Al_bar = 0.57 | u.kg
    steel_bar_roll = 0.31 | u.kg
    steel_wire = 0.053 | u.kg
    Zn_pieces = 0.0079 | (u.m**2)
    Zn_coils = 0.0055 | (u.m**2)
    
    act3 = agb.newActivity(db_name = conf.target_database,
                                name = ACTIVITY_NAME,
                                unit = "unit")
    # Mounting system
    act3.addExchanges({
        agb.findActivity("concrete block production", "DE", db_name=conf.technosphere): concrete, #kg
        agb.findActivity("polyethylene production, high density, granulate", "RER", db_name=conf.technosphere): HDPE, #kg
        agb.findActivity("blow moulding", "RoW", db_name=conf.technosphere): blow_m, #kg
        agb.findActivity("steel production, converter, low-alloyed", "RER", db_name=conf.technosphere): steel_alloy, #kg
        agb.findActivity("aluminium alloy production, AlMg3", "RER", db_name=conf.technosphere): AlMg3, #kg
        agb.findActivity("section bar extrusion, aluminium", "RER", db_name=conf.technosphere): Al_bar, #kg
        agb.findActivity("section bar rolling, steel", "RER", db_name=conf.technosphere): steel_bar_roll, #kg
        agb.findActivity("wire drawing, steel", "RER", db_name=conf.technosphere): steel_wire, #kg
        agb.findActivity("zinc coating, pieces", "RER", db_name=conf.technosphere): Zn_pieces, #m2
        agb.findActivity("zinc coating, coils", "RER", db_name=conf.technosphere): Zn_coils, #m2
        })

    #GCR
    lake_nat_ocup = agb.findActivity("Occupation, lake, natural (non-use)", db_name=conf.biosphere)
    local_coverage_ratio = 0.6 #OK
    act3.addExchanges({lake_nat_ocup : (1.0|(u.m**2))/local_coverage_ratio * conf.power_plant_lifetime})

    return act3

#XXX Modular mounting system
@ensure_activity("PV mounting system vertical on the ground")
def _ensure_mounting_vertical_ground(ACTIVITY_NAME: str, conf):
    """Creates the dataset and related activities for a
    vertical, ground-mounted PV mounting system needed for 1 m2 PV panel.
    Paramaterizes the ecoinvent PV mounting system production
    activity by including the parameters related to the total weight of the
    mounting system, the amount of aluminum, and the amount of wood in kg.
    It also updates the type of steel used for the mounting system.

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    ## Vertical ground system  source
    # https://www.sciencedirect.com/science/article/pii/S2352550925001964
    # 10.1016/j.apenergy.2024.123490
    vertical_ground_system = agb.findActivity(
        'photovoltaic mounting system production, for 570kWp open ground module', 
        db_name=conf.technosphere)

    act4 = agb.copyActivity(
            activity = vertical_ground_system,
            code = ACTIVITY_NAME,
            db_name = conf.target_database,
            withExchanges= False )
    # Reference considers the mounting system can be respresented by the
    # quantities of steel, aluminum, and zinc
    ## ref value fot alu, steel and zinc: 140; 60k and 2.1k kg/MWP
    alu_1MW = 140 | (u.kg/u.MW)
    steel_1MW = 60000 |  (u.kg/u.MW)
    zinc_1MW = 2100 | (u.kg/u.MW)
    # Land use area depends depends on Pitch.
    # Using reference with pitch = 8 m (low). GCR = 25% (10.1016/j.apenergy.2024.123490)
    land_1MW_ha = 1.95 | u.ha
    land_1MW_m2 = land_1MW_ha.to('m**2')/(1|u.MW)
    GCR = 0.25 # GCR = pv_area/ground_occupation_area = row_length/row_pitch= L/R
    pv_area_1MW_m2 = land_1MW_m2*GCR
    # Adjusting the values for the exchanges
    # XXX Question: can we leave exchanges divided by the FU of the activity?
    alu_value = alu_1MW/pv_area_1MW_m2*(1|(u.m**2))
    steel_value = steel_1MW/pv_area_1MW_m2*(1|(u.m**2))
    zinc_value = zinc_1MW/pv_area_1MW_m2*(1|(u.m**2))
    
    steel_act = agb.findActivity('market for reinforcing steel','GLO', db_name=conf.technosphere)
    alu_act = agb.findActivity('market for aluminium, wrought alloy','GLO', db_name=conf.technosphere)
    zinc_act = agb.findActivity('market for zinc','GLO', db_name=conf.technosphere)

    act4.addExchanges({alu_act : alu_value})#kg/m2
    act4.addExchanges({steel_act : steel_value})
    act4.addExchanges({zinc_act : zinc_value})#kg/m2

    #Land use
    transformation_pasture = agb.findActivity('Transformation, from pasture, man made', db_name=conf.biosphere)
    transformation_industrial = agb.findActivity('Transformation, to industrial area', db_name=conf.biosphere)
    occupation = agb.findActivity('Occupation, industrial area', db_name=conf.biosphere)
    
    act4.addExchanges({transformation_pasture : (1.0|(u.m**2))/GCR}) #PV area of 1 m2
    act4.addExchanges({transformation_industrial : (1.0|(u.m**2))/GCR})
    act4.addExchanges({occupation : (1.0|(u.m**2))/GCR * conf.power_plant_lifetime})
    return act4


#XXX Modular mounting system
@ensure_activity("PV mounting for BIPV system")
def _ensure_mounting_vertical_building(ACTIVITY_NAME: str, conf):
    """Creates the dataset and related activities for a building-integrated
    PV mounting system (BIPV).

    Parmeters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    ## facade_system has the same values found in -->  https://iea-pvps.org/wp-content/uploads/2020/12/IEA-PVPS-LCI-report-2020.pdf
    facade_system = agb.findActivity('photovoltaic mounting system production, for facade installation', 'RER', db_name=conf.technosphere)
    # Ecoinvent 3.9: the reference activity holds similar values the IEA document. Key differences are:
        # - locations for all flows correspond to RER, except for those relared to disposal 
        # - flows use activities related to the industrial processes and not global markets
            # removes flows related to transport to avoid double counting
        # - transportation of materials to construction site

    act5 = agb.copyActivity(
            activity = facade_system,
            code = ACTIVITY_NAME,
            db_name = conf.target_database)

    market_wrought_alloy_GLO = agb.findActivity("market for aluminium, wrought alloy", "GLO", db_name=conf.technosphere)
    market_wrought_alloy_RER = agb.copyActivity(    
        activity = market_wrought_alloy_GLO,
        code = "aluminium, wrought alloy [from RER]",
        db_name = conf.target_database,
        withExchanges= False,
    )
    #VALUES market
    # RER+RoW values from original ecoinvent activities
    AL_SCRAP1_RER = market_wrought_alloy_GLO.getAmount(input=agb.findActivity("treatment of aluminium scrap, post-consumer, prepared for recycling, at remelter", "RER", db_name=conf.technosphere))\
       + market_wrought_alloy_GLO.getAmount(input=agb.findActivity("treatment of aluminium scrap, post-consumer, prepared for recycling, at remelter", "RoW", db_name=conf.technosphere)) | u.kg 
    
    AL_SCRAP2_RER = market_wrought_alloy_GLO.getAmount(input=agb.findActivity("treatment of aluminium scrap, new, at remelter", "RER", db_name=conf.technosphere))\
       + market_wrought_alloy_GLO.getAmount(input=agb.findActivity("treatment of aluminium scrap, new, at remelter", "RoW", db_name=conf.technosphere)) | u.kg  | u.kg # IDEM
   
    AL_INGOT_GLO = market_wrought_alloy_GLO.getAmount("aluminium, wrought alloy#GLO") | u.kg # Value from ecoinvent
    
    market_wrought_alloy_RER.addExchanges({
        agb.findActivity("treatment of aluminium scrap, post-consumer, prepared for recycling, at remelter", "RER", db_name=conf.technosphere):AL_SCRAP1_RER,
        agb.findActivity("treatment of aluminium scrap, new, at remelter", "RER", db_name=conf.technosphere): AL_SCRAP2_RER,
        agb.findActivity("aluminium ingot, primary, to aluminium, wrought alloy market", "GLO", db_name=conf.technosphere): AL_INGOT_GLO,
        })

    act5.updateExchanges({
        "polyethylene, high density, granulate":None, #HDPE
        "polystyrene, high impact": None, #HIPS
        "steel, low-alloyed, hot rolled": None, #steel
        "aluminium, wrought alloy": None #aluminium
    })

    #Values
    HDPE = 0.000732 | u.kg
    HIPS = 0.00366 | u.kg
    STEEL = 1.69 | u.kg
    ALU = 2.64 | u.kg
    LORRY = 0.224| (u.t*u.km)
    TRAIN = 1.61| (u.t*u.km)
    LIGHT = 0.444| (u.t*u.km)
    act5.addExchanges({
        agb.findActivity("polyethylene production, high density, granulate","RER", db_name=conf.technosphere): HDPE,
        agb.findActivity("polystyrene production, high impact", "RER",db_name=conf.technosphere) : HIPS,
        agb.findActivity("steel production, low-alloyed, hot rolled", "RER", db_name=conf.technosphere): STEEL,
        market_wrought_alloy_RER : ALU
    })
    if conf.version in {'3.11'}: 
        act5.addExchanges({agb.findActivity('transport, freight, lorry, all sizes, EURO 6*', 'RER', db_name=conf.technosphere): LORRY})
        act5.addExchanges({agb.findActivity('transport, freight, light commercial vehicle, fleet average', 'Europe without Switzerland', db_name=conf.technosphere): LIGHT})
        act5.addExchanges({agb.findActivity('market group for transport, freight, train, fleet average', 'RER', db_name=conf.technosphere): TRAIN})
    else: 
        act5.addExchanges({agb.findActivity('lorry, all sizes, EURO6*', 'RER', db_name=conf.technosphere): LORRY})
        act5.addExchanges({agb.findActivity('transport, freight, light commercial vehicle', 'Europe without Switzerland', db_name=conf.technosphere): LIGHT})
        act5.addExchanges({agb.findActivity('market group for transport, freight train', 'RER', db_name=conf.technosphere): TRAIN})


    return act5


#XXX Modular mounting system
@ensure_activity("PV mounting system")
def _ensure_mounting(ACTIVITY_NAME: str, conf):
    """Creates and parameterizes the PV mounting system dataset and its
    related activities, allowing the selection of the installation mode via
    conf.mounting_system_type.For the selected option, it parameterizes the
    corresponding ecoinvent activity with the total weight, amounts of
    aluminum and wood in kg, and the type of steel used.

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """

    return agb.newSwitchAct(
        name=ACTIVITY_NAME,
        dbname = conf.target_database,
        paramDef = conf.mounting_system_type,
        acts_dict = {
            'ground' : _ensure_mounting_ground(conf),
            'vertical_ground' : _ensure_mounting_vertical_ground(conf),
            'floating_lake' : _ensure_mounting_floating_lake(conf),
            'vertical_building' : _ensure_mounting_vertical_building(conf)
        }
    )


@ensure_activity("photovoltaics, electric installation per kg")
def _ensure_electrical_installation(ACTIVITY_NAME: str, conf):
    """Creates the electrical installation dataset and related activities.
    The electrical installation consists of cables, fuse box,
    lightning protection, etc. without the inverter.

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)
    """
    #VALUES
    WEIGHT_ELEC_3KW = 32.592 #Weight in kg of the electrcal installation for a 3 kWp PV system
    
    # ## Electrical installation

    electrical_installation_3kW = agb.findActivity(
        db_name=conf.technosphere,
        name='photovoltaics, electric installation for 3kWp module, at building',
        loc='RoW')

    # We define a new activity weighting the installations:

    return agb.newActivity(
        db_name = conf.target_database,
        name = ACTIVITY_NAME,
        unit = "kg", # Unit
        exchanges = { # We define exhanges as a dictionarry of 'activity : amount'
            electrical_installation_3kW : 1.0/WEIGHT_ELEC_3KW
        }
    )

# TODO verify hypothesis 
@ensure_activity("Inverter production, P kW per kg")
def _ensure_inverter(ACTIVITY_NAME: str, conf):
    """Creates the inverter dataset and related activities.
    The representative flow of the inverter activity is the production of
    1 kg of inverter.

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    # ## Inverter

    # From a 3 kVA inverter to a 570 kVA inverter, there is a significant
    # evolution in the share material used.
    # The inventory will be calculated based on the weight of the inverter
    # multiplied by the share of the different material involved interpolated
    # between the 3 KVA and 570 kVA inventories.

    # ### Parameterized function for inverter

    # Recycling activities
    if conf.version in {'3.11'} : 
        scrap_alu = agb.findActivity('aluminium scrap, post-consumer, Recycled Content cut-off','GLO', db_name=conf.technosphere)
        scrap_steel = agb.findActivity('iron scrap, unsorted, Recycled Content cut-off','GLO', db_name=conf.technosphere)
        scrap_coper = agb.findActivity("copper scrap, sorted, pressed, Recycled Content cut-off", db_name=conf.technosphere)
    else:
       scrap_alu = agb.findActivity('market for scrap aluminium','Europe without Switzerland', db_name=conf.technosphere)
       scrap_steel = agb.findActivity('market for scrap steel','Europe without Switzerland', db_name=conf.technosphere)
       scrap_coper = agb.findActivity("market for scrap copper", "Europe without Switzerland", db_name=conf.technosphere)  
    
    scrap_electronic = agb.findActivity("market for electronics scrap", db_name=conf.technosphere)

    inverter_500kW = agb.findActivity('inverter production, 500kW', 'RER', db_name=conf.technosphere)
    inverter_2500W = agb.findActivity('inverter production, 2.5kW', 'RER', db_name=conf.technosphere)
    weigth_2500W = 18.5 | u.kg
    weigth_500kW = 3000.0 | u.kg

    inverter_2500W_with_recycling = agb.copyActivity(
        db_name  = conf.target_database,
        activity=inverter_2500W,
        code=f"{conf.prefix}inverter production with recycling, 2.5kW")

    # Add recycling
    amount_alu = inverter_2500W.getAmount('aluminium, cast alloy*')
    amount_copper = inverter_2500W.getAmount('copper, cathode*')
    amount_steel = inverter_2500W.getAmount('steel, low-alloyed, hot rolled*')
    amount_electronic = inverter_2500W.getAmount([
            'capacitor*',
            'diode*',
            'integrated circuit*',
            'printed wiring*',
            'resistor*',
            'transitor*'
        ], sum=True)

    inverter_2500W_with_recycling.addExchanges({
        scrap_alu : (amount_alu*u.kg) * conf.recycling_rate,
        scrap_coper : (amount_copper*u.kg) * conf.recycling_rate,
        scrap_electronic : (amount_electronic*u.kg) * conf.recycling_rate,
        scrap_steel : (amount_steel*u.kg) * conf.recycling_rate
    })

    inverter_500kW_with_recycling = agb.copyActivity(
        db_name  = conf.target_database,
        activity=inverter_500kW,
        code=f"{conf.prefix}inverter production with recycling, 500kW")

    # Add recycling
    amount_alu = inverter_500kW.getAmount('aluminium, cast alloy*')
    amount_copper = inverter_500kW.getAmount('copper, cathode*')
    amount_steel = inverter_500kW.getAmount('steel, low-alloyed, hot rolled*')
    amount_electronic = inverter_500kW.getAmount([
            'capacitor*',
            'diode*',
            'integrated circuit*',
            'printed wiring*',
            'resistor*',
            'transitor*'
        ], sum=True)

    inverter_500kW_with_recycling.addExchanges({
        scrap_alu : (amount_alu*u.kg) * conf.recycling_rate,
        scrap_coper : (amount_copper*u.kg) * conf.recycling_rate,
        scrap_electronic : (amount_electronic*u.kg) * conf.recycling_rate,
        scrap_steel : (amount_steel*u.kg) * conf.recycling_rate
    })

    inverter_2500W_per_kg = agb.newActivity(
        db_name = conf.target_database,
        name = f'{conf.prefix}inverter production, 2.5kW per kg',
        unit = "kg", # mean kilogram of inverter
        exchanges = { inverter_2500W_with_recycling : (1.0|weigth_2500W.u)/weigth_2500W } # ensure unit less unit
    )

    inverter_500kW_per_kg = agb.newActivity(
        db_name = conf.target_database,
        name = f'{conf.prefix}inverter production, 500kW per kg',
        unit = "kg", # mean kilogram of inverter
        exchanges = { inverter_500kW_with_recycling : (1.0|weigth_500kW.u)/weigth_500kW }
    )

    # Generate a dataset for 1kG of inverter, based on the power
    #FIXME : interpolation has an error with lca_algebraic units
    # testing with inverter_500kW_per_kg for now
    return agb.interpolate_activities(
        db_name = conf.target_database,
        act_name = ACTIVITY_NAME,
        param=conf.inverter_power_capacity,
        act_per_value={
            0.0 | u.kW : inverter_2500W_per_kg,
            2.5 | u.kW : inverter_2500W_per_kg,
            500.0 | u.kW : inverter_500kW_per_kg,
            1e30 | u.kW : inverter_500kW_per_kg
        }
    )


@ensure_activity("market for silicon, solar grade")
def _ensure_market_silicon(ACTIVITY_NAME: str, conf):
    """Creates the silicon dataset and related activities.
    Updates the dataset with the findings of Besseau et al. (2023)

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    elec_switch_act = _ensure_electricity(conf)

    # ## Silicon production
    # #### For MG grade
    act = agb.findActivity('silicon production, metallurgical grade', 'NO', db_name=conf.technosphere) #production in Europe, Norway
    silicon_production_metallurgical_grade = agb.copyActivity(
        db_name = conf.target_database,
        activity = act,
        code = f"{conf.prefix}silicon production, metallurgical grade"
    )

    #Adjust the electricity mix
    silicon_production_metallurgical_grade.updateExchanges(updates = {
        'electricity, medium voltage*' : elec_switch_act
    })

    # #### For Solar Grade silicon
    act = agb.findActivity('silicon production, solar grade, modified Siemens process', 'RER', db_name=conf.technosphere)
    silicon_production_solar_grade = agb.copyActivity(
        db_name = conf.target_database,
        activity = act,
        code = f"{conf.prefix}silicon production, solar grade, modified Siemens process")
    # Link to the parameterized MG Si dataset
    silicon_production_solar_grade.updateExchanges({
        "silicon, metallurgical grade*": silicon_production_metallurgical_grade
    })

    # Remove all electricity sources and replace them by the selected
    # electricity mix.
    silicon_production_solar_grade.updateExchanges(updates={'electricity*': None})
    silicon_production_solar_grade.addExchanges({elec_switch_act: conf.silicon_production_electricity_intensity})
    silicon_production_solar_grade.updateExchanges({"heat*": conf.silicon_production_heat_intensity})
    # -

    # #### Market for silicon solar grade

    act = agb.findActivity('market for silicon, solar grade', db_name=conf.technosphere)

    market_for_silicon_solar_grade = agb.copyActivity(db_name = conf.target_database,
                                    activity = act,
                                    code = ACTIVITY_NAME)
    #link to the parameterized MG Si dataset
    market_for_silicon_solar_grade.updateExchanges({"silicon*": None})
    market_for_silicon_solar_grade.addExchanges({silicon_production_solar_grade: (1.0|u.kg)})

    return market_for_silicon_solar_grade

@ensure_activity("silicon carbide production")
def _ensure_silicon_carbide_recycled(ACTIVITY_NAME: str, conf):
    """Creates the silicon carbide production activities.
    Updates the dataset with the findings of Besseau et al. (2023)

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    silicon_carbide = agb.findActivity('silicon carbide production', 'RER', db_name=conf.technosphere)
    silicon_carbide_recycled = agb.copyActivity(db_name = conf.target_database,
                                                activity = silicon_carbide,
                                                code = ACTIVITY_NAME,
                                                withExchanges = False)
    # Silicon carbide values
    sic_ELEC = 0.78571 | u.kWh
    sic_LORRY = 0.2625 | (u.t*u.km)
    sic_SI = 1e-11 #unit, dimensionless
    sic_HEAT = 2.8286 | u.megajoule
    sic_WAFER_WASTE = -0.042857 | u.kg
    sic_WASTE_TREAT = -0.071429 | u.kg
    sic_IRON = -0.13571 | u.kg
    #Change to 'RoW' is the waste is not produced in Europe
    lc = 'RoE' if conf.version in {'3.10.1', '3.10', '3.11'} else 'GLO'

    silicon_carbide_recycled.addExchanges(exchanges = {
        agb.findActivity('market group for electricity, medium voltage', 'ENTSO-E', db_name=conf.technosphere) : sic_ELEC,
        agb.findActivity('market for transport, freight, lorry, unspecified', 'RER', db_name=conf.technosphere) : sic_LORRY,
        agb.findActivity('market for silicone factory', db_name=conf.technosphere) : sic_SI,
        agb.findActivity('Heat, waste', categories=['air'],db_name=conf.biosphere) : sic_HEAT,
        agb.findActivity('market for waste, from silicon wafer production, inorganic', loc=lc, db_name=conf.technosphere) : sic_WAFER_WASTE,
        agb.findActivity('treatment of spent antifreezer liquid, hazardous waste incineration', 'CH', db_name=conf.technosphere) : sic_WASTE_TREAT,
        agb.findActivity('market for pig iron', 'RER', db_name=conf.technosphere) : sic_IRON,
    })

    return silicon_carbide_recycled

@ensure_activity("tungstene carbide production")
def _ensure_tungstene_carbide(ACTIVITY_NAME: str, conf):
    """Creates the tungstene carbide production activities.
    Updates the dataset with the findings of Besseau et al. (2023)

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    # ##### Tungstene

    # This activity is {name: 'sulfuric acid production', loc='RER', reference product: 'steam, in chemical industry'}
    # It the one used by Romain (2019) but it seems to be wrong, it should be replaced by the one below
    #act_sulfuric_acid = getActByCode(db_name=conf.technosphere, code='4c9bd1eb18a182413455faa532d6532b')
    # This activity is {name: 'sulfuric acid production', loc='RER', reference product: 'sulfuric acid'}
    # This is the one that should be used.
    #act_sulfuric_acid = getActByCode(db_name=conf.technosphere, code='168c76950bbe49d9e0e63ec7f36a7a26')

    # try if this activity is available, if not we are using ecoinvent >3.7
    try:
        # This activity is the wrong one but it is the one used by Romain 2019
        act_sulfuric_acid = getActByCode(db_name=conf.technosphere, code='4c9bd1eb18a182413455faa532d6532b')
        print("WARNING: Using wrong 'sulfuric acid production' activity for backward compliance")
    except:
        act_sulfuric_acid = None

    # This is the actual activity required by Romain 2019
    if act_sulfuric_acid is None:
        act_sulfuric_acid = get_acurate_activities(conf.technosphere, {
            "name":'sulfuric acid production',
            "location":'RER',
            "reference product": 'sulfuric acid'
        })

        if len(act_sulfuric_acid) != 1:
            raise Exception("No proper 'sulfuric acid production' activity found.")
        act_sulfuric_acid = act_sulfuric_acid[0]

    silicon_carbide = agb.findActivity('silicon carbide production', 'RER', db_name=conf.technosphere)
    tungstene_carbide = agb.copyActivity(
        db_name = conf.target_database,
        activity = silicon_carbide,
        code = ACTIVITY_NAME,
        withExchanges = False)

    # Tungsten carbide values from
    # Bianco (2018), pg 113 : https://iris.polito.it/retrieve/e384c430-13f1-d4b2-e053-9f05fe0a1d67/Bianco_Isabella_PhD_Thesis.pdf
    W_NaOH = 1.49 | u.kg
    W_Alsulf = 0.071 | u.kg
    W_SodSulf = 0.044 | u.kg
    W_Mgsulf = 0.027 | u.kg
    W_ammonia = 0.106 | u.kg
    W_soda_ash = 1.21 | u.kg
    W_sulfuric_acid = 1.24 | u.kg
    W_elec = 111.16 |u.kWh
    W_H2sulf = 0.0076 | u.kg
    W_N2 = 1.65 | u.kg
    W_H2 = 0.32 | u.kg
    W_water = 2.84 | u.kg
    W_Cblack = 0.13 | u.kg
    
    if conf.version in {'3.10.1', '3.10', '3.11'}:
        H2='market for hydrogen, gaseous, medium pressure, merchant'
        lc='RER'
    else:
        H2 = 'market for hydrogen, liquid'
        lc = 'GLO'
        
    tungstene_carbide.addExchanges({
        agb.findActivity('market for sodium hydroxide, without water, in 50% solution state', loc=lc, db_name=conf.technosphere) : W_NaOH,
        agb.findActivity('aluminium sulfate production, powder', 'RER', db_name=conf.technosphere) : W_Alsulf,
        agb.findActivity('sodium sulfide production', db_name=conf.technosphere) : W_SodSulf,
        agb.findActivity('magnesium sulfate production', 'RER', db_name=conf.technosphere) : W_Mgsulf,
        agb.findActivity('market for ammonia, anhydrous, liquid', 'RER', db_name=conf.technosphere) : W_ammonia,
        agb.findActivity('market for soda ash, dense', db_name=conf.technosphere) : W_soda_ash,
        act_sulfuric_acid : W_sulfuric_acid,
        agb.findActivity('market group for electricity, medium voltage', 'ENTSO-E', db_name=conf.technosphere) : W_elec,
        agb.findActivity('hydrogen sulfide production', 'RER', db_name=conf.technosphere) : W_H2sulf,
        agb.findActivity('market for nitrogen, liquid', 'RER', db_name=conf.technosphere) : W_N2,
        agb.findActivity(H2, 'RER', db_name=conf.technosphere) : W_H2,
        agb.findActivity('market for tap water', 'RoW', db_name=conf.technosphere) : W_water,
        agb.findActivity('carbon black production', db_name=conf.technosphere) : W_Cblack,
        })

    return tungstene_carbide


@ensure_activity("diamond production, powder")
def _ensure_diamond_powder(ACTIVITY_NAME: str, conf):
    """Creates the diamond production, powder activities.
    Updates the dataset with the findings of Besseau et al. (2023)

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    diamond_powder_ori = agb.findActivity('sodium percarbonate production, powder', 'RER', db_name=conf.technosphere)
    diamond_powder = agb.copyActivity(db_name = conf.target_database,
                                      activity = diamond_powder_ori,
                                      code = ACTIVITY_NAME,
                                      withExchanges = False)
    
    #diamond values from Bianco (2018) pg 151
    diam_elec = 840 | u.kWh
    diam_graphite = 1 | u.kg
    diam_SHIP = 170 | (u.t*u.km)
    diam_LORRY = 0.53 | (u.t*u.km)
    
    diamond_powder.addExchanges({
        agb.findActivity("market group for electricity, medium voltage", "GLO", db_name=conf.technosphere) : diam_elec,
        agb.findActivity("graphite production", "RER", db_name=conf.technosphere) : diam_graphite,
    })
    if conf.version in {'3.11'}: 
        diamond_powder.addExchanges({agb.findActivity("transport, freight, lorry, 16-32 metric ton, diesel, EURO 4", "RER", db_name=conf.technosphere) : diam_LORRY,})
        diamond_powder.addExchanges({agb.findActivity("market for transport, freight, sea, container ship, heavy fuel oil", db_name=conf.technosphere) : diam_SHIP})
    else:
        diamond_powder.addExchanges({agb.findActivity("transport, freight, lorry 16-32 metric ton, EURO4", "RER", db_name=conf.technosphere) : diam_LORRY,})
        diamond_powder.addExchanges({agb.findActivity("market for transport, freight, sea, container ship", db_name=conf.technosphere) : diam_SHIP})
    
    return diamond_powder


@ensure_activity("sintered diamond bead, for quarrying")
def _ensure_sintered_diamond(ACTIVITY_NAME: str, conf):
    """Creates the sintered diamond bead, for quarrying activities.
    Updates the dataset with the findings of Besseau et al. (2023)

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    # +
    sintered_diamond_ori = agb.findActivity("polymethyl methacrylate production", "RER", db_name=conf.technosphere) if conf.version in {'3.11'}\
        else agb.findActivity("polymethyl methacrylate production, beads", "RER", db_name=conf.technosphere)

    sintered_diamond = agb.copyActivity(db_name = conf.target_database,
                                        activity = sintered_diamond_ori,
                                        code = ACTIVITY_NAME,
                                        withExchanges=False)
   
    # Data from Bianco's thesis - -used values from Figure 73
    #FIXME: check values because some change from the original PARASOL_LCA - changed values and units
    #Sintererd diamond values from Bianco (2018) pg 122
    bead_elec = 0.1 |u.kWh
    bead_steel = 0.003 | u.kg
    bead_cobalt = 1.2e-04 | u.kg
    bead_copper = 7e-05 | u.kg
    bead_iron = 3.5e-04 | u.kg
    bead_nickel = 2.1e-05 | u.kg
    bead_W = 3.5e-05 | u.kg
    bead_diam_powder = 2e-05 | u.kg
    bead_thick = 2e-05 | u.kg    
    bead_Ar = 2.1e-04 | u.kg
    bead_N = 0.0323 | u.kg
    bead_H = 9e-04 | u.kg
    
    if conf.version in {'3.10.1', '3.10', '3.11'}:
        H2='market for hydrogen, gaseous, medium pressure, merchant'
    else:
        H2 = 'market for hydrogen, liquid'
    
    

    sintered_diamond.addExchanges({
        agb.findActivity("market group for electricity, medium voltage", "ENTSO-E", db_name=conf.technosphere) : bead_elec,
        agb.findActivity("market for steel, unalloyed", "GLO", db_name=conf.technosphere) : bead_steel,
        agb.findActivity("market for cobalt", db_name=conf.technosphere) : bead_cobalt,# Original PARASOL_LCA: 7e-08,
        agb.findActivity("market for copper, anode", db_name=conf.technosphere) : bead_copper, # Original PARASOL_LCA: 2.1e-07,
        agb.findActivity("market for pig iron", 'RER', db_name=conf.technosphere) : bead_iron,# Original PARASOL_LCA:3.5e-07,
        agb.findActivity("market for nickel, class 1", db_name=conf.technosphere) : bead_nickel, # Original PARASOL_LCA: 2.1e-08,
        _ensure_tungstene_carbide(conf) : bead_W,# Original PARASOL_LCA: 3.5e-08,
        _ensure_diamond_powder(conf) : bead_diam_powder,
        sintered_diamond_ori :  bead_thick,
        # Original PARASOL_LCA: double market for cobalt activity
        #agb.findActivity("market for cobalt", db_name=conf.technosphere) : 5e-05,
        agb.findActivity("market for silver", db_name=conf.technosphere) : bead_Ar,
        agb.findActivity("market for nitrogen, liquid", "RER", db_name=conf.technosphere) : bead_N,
        agb.findActivity(H2, "RER", db_name=conf.technosphere) : bead_H
    })

    sintered_diamond.setOutputAmount(0.004) #kg

    return sintered_diamond


@ensure_activity("sintered diamond wire, steel")
def _ensure_sintered_diamond_wire(ACTIVITY_NAME: str, conf):
    """Creates the sintered diamond wire, steel activities.
    Updates the dataset with the findings of Besseau et al. (2023)

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    # ##### Sintered diamond bead
    sintered_diamond = _ensure_sintered_diamond(conf)

    # ##### Sintered diamond wire
    try:
        # activity from =3.7
        polyurethane = agb.findActivity("polyurethane production, flexible foam", "RER", db_name=conf.technosphere)
    except:
        # activity from >3.7
        polyurethane = agb.findActivity("polyurethane production, flexible foam, MDI-based", "RER", db_name=conf.technosphere)

    act_ori = agb.findActivity('wire drawing, steel', 'RER', db_name=conf.technosphere)
    sintered_diamond_wire = agb.copyActivity(
        db_name = conf.target_database,
        activity = act_ori,
        code = ACTIVITY_NAME,
        withExchanges = False)
    
    # Sintered diamond wire values from Bianco (2018) pg 117-118
    wire_bead = 0.0427 | u.kg
    wire_elec = 0.9 | u.kWh
    wire_steel= 0.095 | u.kg
    wire_poly = 0.15 | u.kg
    wire_LORRY = 0.003 | (u.t*u.km)
    wire_waste = -0.045 | u.kg # Fixed: was positive before

    sintered_diamond_wire.addExchanges({
        sintered_diamond : wire_bead,
        agb.findActivity("market group for electricity, medium voltage", "ENTSO-E", db_name=conf.technosphere) : wire_elec,
        agb.findActivity("wire drawing, steel", "RER", db_name=conf.technosphere) : wire_steel,
        polyurethane : wire_poly,
        agb.findActivity("market for waste plastic, mixture", "RoW", db_name=conf.technosphere) : wire_waste
    })
    
    if conf.version in {'3.11'}: 
        sintered_diamond_wire.addExchanges({agb.findActivity("transport, freight, lorry, 16-32 metric ton, diesel, EURO 4", "RER", db_name=conf.technosphere) : wire_LORRY})
    else:
        sintered_diamond_wire.addExchanges({agb.findActivity("transport, freight, lorry 16-32 metric ton, EURO4", "RER", db_name=conf.technosphere) : wire_LORRY})

    return sintered_diamond_wire


@ensure_activity("multi-Si wafer production")
def _ensure_wafer_multi_si(ACTIVITY_NAME: str, conf):
    """Creates the silicon dataset and related activities.
    Updates the dataset with the findings of Besseau et al. (2023)

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    elec_switch_act = _ensure_electricity(conf)

    # #### Silicon production Si casted - for multi-Si

    act = agb.findActivity('silicon production, multi-Si, casted', 'RER', db_name=conf.technosphere)

    # Let's remove the use of silicon electronics grade, the share was significant when the world silicon production was relatively low, nowadays volume can be neglected compared to the level reached by the solar industry.

    market_silicon = _ensure_market_silicon(conf)

    silicon_production_multi_si_casted = agb.copyActivity(db_name = conf.target_database,
                                    activity = act,
                                    code = f"{conf.prefix}silicon production, multi-Si, casted")
    #link to the parameterized MG Si dataset
    silicon_production_multi_si_casted.updateExchanges({"silicon,*": None})

    silicon_production_multi_si_casted.updateExchanges({"electricity, medium voltage*": elec_switch_act})
    silicon_production_multi_si_casted.updateExchanges({"electricity, medium voltage*": conf.silicon_casting_electricity_intensity})
    silicon_production_multi_si_casted.addExchanges({market_silicon: (1.0|u.kg)})

    # ####  Market for Si casted

    act = agb.findActivity('market for silicon, multi-Si, casted','RER', db_name=conf.technosphere)
    market_silicon_multi_si_casted = agb.copyActivity(db_name = conf.target_database,
                                    activity = act,
                                    code = f"{conf.prefix}market for silicon, multi-Si, casted")
    #link to the parameterized MG Si dataset
    market_silicon_multi_si_casted.updateExchanges({"silicon*": None})
    market_silicon_multi_si_casted.addExchanges({silicon_production_multi_si_casted:(1.0|u.kg)})

    # ### Wafer manufacturing
    # #### Cutting process
    # ##### SiC, Recycled
    silicon_carbide_recycled = _ensure_silicon_carbide_recycled(conf)

    # #### Diamond Wiring
    sintered_diamond_wire = _ensure_sintered_diamond_wire(conf)

    # #### Wafer
    # Values
    wafer_thick_meter = conf.wafer_thickness.to(u.m) # from millimeter to meter
    sic_value = 2328.0|(u.kg/u.m)
    diamond_wiring_fixed = conf.diamond_wiring*1.0 |u.ratio
    
    # Formulas
    # Integrate gain in kerf loss for diamond wiring
    kerf_loss_adapted = conf.kerf_loss - 0.15 * conf.diamond_wiring
    sili_casting_amount = wafer_thick_meter * sic_value / (1 - kerf_loss_adapted)
    non_diamond_wiring = 1 - diamond_wiring_fixed #dimensionless

    # Copy Wafer
    wafer = agb.findActivity("multi-Si wafer production", "RER", db_name=conf.technosphere)
    wafer_adjusted = agb.copyActivity(
        db_name = conf.target_database,
        activity = wafer,
        code = ACTIVITY_NAME)

    # Update wafer
    # Values
    teg_recycled_share = 0.0
    sic_amount = 2.02988 | u.kg
    tglyc_value = 2.16548 | u.kg
    diam_wire_value = 0.0006075|u.kg
    elec_value = 8 |u.kWh
    heat_value = 3.6 |u.megajoule
    sic_new_value = non_diamond_wiring * sic_amount * (1.0 - conf.sic_recycled_share)
    tglyc_new_value = non_diamond_wiring * tglyc_value * (1.0 - teg_recycled_share)

    wafer_adjusted.updateExchanges({
        'silicon, multi-Si, casted*' : dict(
            input = market_silicon_multi_si_casted,
            amount = sili_casting_amount,
            name='silicon production, adjusted'),
        'silicon carbide*' : sic_new_value,
        'triethylene glycol*' : tglyc_new_value
    })

    wafer_adjusted.addExchanges({
        # Diamond wiring (see also Tap water updated above)
        sintered_diamond_wire :  diamond_wiring_fixed * diam_wire_value,
        # Non -diamond wiring
        silicon_carbide_recycled : non_diamond_wiring * sic_amount * conf.sic_recycled_share
        })

    #Adapts the amount of electricity to be used
    wafer_adjusted.updateExchanges({"electricity, medium voltage*": elec_value * (1 - conf.manufacturing_efficiency_gains)})
    wafer_adjusted.updateExchanges({"heat, district or industrial, natural gas*": heat_value * (1 - conf.manufacturing_efficiency_gains)})
    #Adapts the dataset to be used
    wafer_adjusted.updateExchanges({"electricity*": elec_switch_act})

    return wafer_adjusted

# FIXME to check the single-Si hypotheses
# From ecoinvent, Si is produced the same way but it diverges when the wafer is made
@ensure_activity("single-Si wafer production, photovoltaic")
def _ensure_wafer_mono_si(ACTIVITY_NAME: str, conf):
    """
    Creates the silicon dataset and related activities.
    Updates the dataset with the findings of Besseau et al. (2023)

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity
    """
    
    elec_switch_act = _ensure_electricity(conf)

    # #### Silicon production Si casted - for multi-Si

    act = agb.findActivity('silicon production, single crystal, Czochralski process, photovoltaics', 'RER', db_name=conf.technosphere)

    # Let's remove the use of silicon electronics grade, the share was significant when the world silicon production was relatively low, nowadays volume can be neglected compared to the level reached by the solar industry.

    market_silicon = _ensure_market_silicon(conf)

    silicon_production_single_si_photovoltaics = agb.copyActivity(db_name = conf.target_database,
                                    activity = act,
                                    code = f"{conf.prefix}silicon production, single crystal, Czochralski process, photovoltaics")
    #link to the parameterized MG Si dataset
    silicon_production_single_si_photovoltaics.updateExchanges({"silicon,*": None})
    silicon_production_single_si_photovoltaics.updateExchanges({"electricity, medium voltage*": elec_switch_act})
    silicon_production_single_si_photovoltaics.updateExchanges({"electricity, medium voltage*": conf.silicon_casting_electricity_intensity})
    silicon_production_single_si_photovoltaics.addExchanges({market_silicon:  (1.0|u.kg)})

    # ####  Market for Si casted

    act = agb.findActivity('market for silicon, single crystal, Czochralski process, photovoltaics','RER', db_name=conf.technosphere)

    market_silicon_single_si_photovoltaics = agb.copyActivity(db_name = conf.target_database,
                                    activity = act,
                                    code = f"{conf.prefix}market for silicon, single crystal, Czochralski process, photovoltaics")
    #link to the parameterized MG Si dataset
    market_silicon_single_si_photovoltaics.updateExchanges({"silicon*": None})
    market_silicon_single_si_photovoltaics.addExchanges({silicon_production_single_si_photovoltaics:(1.0|u.kg)})

    # ### Wafer manufacturing
    # #### Cutting process
    # ##### SiC, Recycled
    silicon_carbide_recycled = _ensure_silicon_carbide_recycled(conf)

    # #### Diamond Wiring
    sintered_diamond_wire = _ensure_sintered_diamond_wire(conf)

    # Formulas
    wafer_thick_meter = conf.wafer_thickness.to(u.m) # from millimeter to meter
    sic_value = 2328.0|(u.kg/u.m)
    diamond_wiring_fixed = conf.diamond_wiring*1.0 |u.ratio

    # Integrate gain in kerf loss for diamond wiring
    kerf_loss_adapted = conf.kerf_loss - 0.15 * conf.diamond_wiring
    sili_casting_amount = wafer_thick_meter * sic_value / (1 - kerf_loss_adapted)
    non_diamond_wiring = 1 - diamond_wiring_fixed #dimensionless

    # Copy Wafer
    wafer = agb.findActivity("single-Si wafer production, photovoltaic", "RER", db_name=conf.technosphere)
    wafer_adjusted = agb.copyActivity(
        db_name = conf.target_database,
        activity = wafer,
        code = ACTIVITY_NAME)

    # Values
    # FIXME : to check if they correspond to the literature on monoSi manufacturing
    teg_recycled_share = 0.0
    sic_amount = 2.02988 | u.kg
    tglyc_value = 2.16548 | u.kg
    diam_wire_value = 0.0006075|u.kg
    elec_value = 8 |u.kWh
    heat_value = 3.6 |u.megajoule
    sic_new_value = non_diamond_wiring * sic_amount * (1.0 - conf.sic_recycled_share)
    tglyc_new_value = non_diamond_wiring * tglyc_value * (1.0 - teg_recycled_share)

    wafer_adjusted.updateExchanges({
        'silicon, single crystal, Czochralski process, photovoltaics*' : dict(
            input = market_silicon_single_si_photovoltaics,
            amount = sili_casting_amount,
            name='silicon production, adjusted'),
        'silicon carbide*' : sic_new_value,
        'triethylene glycol*' : tglyc_new_value
    })

    wafer_adjusted.addExchanges({
        # Diamond wiring (see also Tap water updated above)
        sintered_diamond_wire :  diamond_wiring_fixed * diam_wire_value,
        # Non -diamond wiring
        silicon_carbide_recycled : non_diamond_wiring * sic_amount * conf.sic_recycled_share
        })

    #Adapts the amount of electricity to be used
    wafer_adjusted.updateExchanges({"electricity, medium voltage*": elec_value * (1 - conf.manufacturing_efficiency_gains)})
    wafer_adjusted.updateExchanges({"heat, district or industrial, natural gas*": heat_value * (1 - conf.manufacturing_efficiency_gains)})
    #Adapts the dataset to be used
    wafer_adjusted.updateExchanges({"electricity*": elec_switch_act})

    return wafer_adjusted


def _metalisation_fomulae(conf):
    """Creates the metalisation dataset.
    Needed for the multi-Si cell and panel datasets.

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    # To adapt the amount of **Silver** used for the *metallic contact*:
    # - By default, for the front side : 7.4 g/m² Silver based paste corresponding to 6.2 g/m² of Ag (84% Silver)
    # - By default, for the back side : 4.9 g/m² Silver based paste corresponding to 3.3 g/m² of Ag (67% Silver)
    # - An additional 0.7 g of Ag is used is anyway considered for the panel.
    #
    # To add the **copper paste** used to *substitute the amount of Silver use*:
    # - The amount of copper is calculated considering the difference of conductivity between Ag and Cu
    # - Conductiviy of Ag = 6.3e7 S/m, Cu = 5.96e7 S/m at 20°C
    
    #Values
    Ag_p_front = 7.4e-3 |u.kg
    Ag_p_back = 4.9e-3 |u.kg
    Ag_extra = 0.7 |(u.g/(u.m**2))
    Ag_84 = 6.2 |(u.g/(u.m**2))
    Ag_67 = 3.3 |(u.g/(u.m**2))
    zero = 0|u.kg
    
    front_silver_amount = agb.Max(Ag_p_front * (conf.silver_content - Ag_extra)  / (Ag_84 + Ag_67), zero)
    back_silver_amount = agb.Max(Ag_p_back * (conf.silver_content - Ag_extra)  / (Ag_84 + Ag_67), zero)

    return front_silver_amount, back_silver_amount

@ensure_activity("photovoltaic cell production, multi-Si wafer - adjusted")
def _ensure_pv_cell_manufacturing_multi_si(ACTIVITY_NAME: str, conf):
    """Create the PV cell manufacturing dataset and related activities.

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity

    """
    wafer_adjusted = _ensure_wafer_multi_si(conf)
    elec_switch_act = _ensure_electricity(conf)

    # ## PV cell manufacturing
    cell_init = agb.findActivity('photovoltaic cell production, multi-Si wafer', 'RER', db_name=conf.technosphere)

    # VALUES
    elec_value = 30.243|u.kWh
    
    front_silver_amount, back_silver_amount = _metalisation_fomulae(conf)

    cell_adjusted = agb.copyActivity(db_name = conf.target_database,
                                     activity = cell_init,
                                     code = ACTIVITY_NAME)

    try:
        cell_adjusted.updateExchanges({
        'metallization paste, front side' : front_silver_amount,
        'metallization paste, back side': back_silver_amount,
        'multi-Si wafer' : dict(input=wafer_adjusted)
        })
    except: #premise
        cell_adjusted.updateExchanges({
            'market for metallization paste, front side' : front_silver_amount,
            'market for metallization paste, back side': back_silver_amount,
            'market for multi-Si wafer' : dict(input=wafer_adjusted)
        })

    #Adapt the quantity of electricity to use
    cell_adjusted.updateExchanges({'electricity, medium voltage*': elec_value * (1 - conf.manufacturing_efficiency_gains)})
    #Adapt the dataset to use
    cell_adjusted.updateExchanges({'electricity, medium voltage*': elec_switch_act})

    return cell_adjusted

# FIXME to check the single-Si hypotheses
@ensure_activity("photovoltaic cell production, single-Si wafer - adjusted")
def _ensure_pv_cell_manufacturing_single_si(ACTIVITY_NAME: str, conf):
    """
    Create the PV cell manufacturing dataset and related activities.
    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity
    """
    
    wafer_adjusted = _ensure_wafer_mono_si(conf)
    elec_switch_act = _ensure_electricity(conf)

    # ## PV cell manufacturing

    cell_init = agb.findActivity('photovoltaic cell production, single-Si wafer', 'RER', db_name=conf.technosphere)
    
    # VALUES
    elec_value = 30.243|u.kWh
    
    front_silver_amount, back_silver_amount = _metalisation_fomulae(conf)

    cell_adjusted = agb.copyActivity(db_name = conf.target_database,
                                     activity = cell_init,
                                     code = ACTIVITY_NAME)

    try:
        cell_adjusted.updateExchanges({
        'metallization paste, front side' : front_silver_amount,
        'metallization paste, back side': back_silver_amount,
        'single-Si wafer, photovoltaic' : dict(input=wafer_adjusted)
        })
    except: #premise
        cell_adjusted.updateExchanges({
            'market for metallization paste, front side' : front_silver_amount,
            'market for metallization paste, back side': back_silver_amount,
            'market for single-Si wafer, photovoltaic' : dict(input=wafer_adjusted)
        })

    #Adapt the quantity of electricity to use
    cell_adjusted.updateExchanges({'electricity, medium voltage*': elec_value * (1 - conf.manufacturing_efficiency_gains)})
    #Adapt the dataset to use
    cell_adjusted.updateExchanges({'electricity, medium voltage*': elec_switch_act})

    return cell_adjusted


@ensure_activity("photovoltaic panel production, multi-Si wafer - adjusted")
def _ensure_pv_panel_multi_si(ACTIVITY_NAME: str, conf):
    """
    Create the PV panel manufacturing dataset and related activities.

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity
    """
    """
    ## PV panel
    """
    # Values
    zero = 0|u.kg
    silver_value = 9.6e-3|u.kg
    
    elec_switch_act = _ensure_electricity(conf)
    front_silver_amount, back_silver_amount = _metalisation_fomulae(conf)

    new_front_silver_amount = 0.84 * front_silver_amount
    new_back_silver_amount = 0.67 * back_silver_amount
    copper_amount = agb.Max(1/0.67 * 6.3e7 / 5.96e7 * ( silver_value -(new_front_silver_amount + new_back_silver_amount)), zero)
    new_copper_amount = 0.67 * copper_amount |u.kg
    
    # ## PV panel
    panel_init = agb.findActivity('photovoltaic panel production, multi-Si wafer', 'RER', db_name=conf.technosphere)

    cell_adjusted = _ensure_pv_cell_manufacturing_multi_si(conf)
    
    #Ecoinvent version
    scrapAlu = agb.findActivity('market for aluminium scrap, new', 'RER', db_name=conf.technosphere) if conf.version in {'3.11'} \
    else agb.findActivity('market for scrap aluminium*', 'Europe without Switzerland', db_name=conf.technosphere) 
    
    # Activities
    scrapGlass = agb.findActivity('market for waste glass sheet', 'Europe without Switzerland', db_name=conf.technosphere)
    
    scrapCopper = agb.findActivity("copper scrap, sorted, pressed, Recycled Content cut-off", db_name=conf.technosphere) if conf.version in {'3.11'} \
        else agb.findActivity('market for scrap copper*', 'Europe without Switzerland', db_name=conf.technosphere)  
    
    heat_for_recycling = agb.findActivity('heat and power co-generation, biogas, gas engine',
                                         loc = 'RoW', unit = 'megajoule', db_name=conf.technosphere)

    # Base activity
    panel_init = agb.findActivity('photovoltaic panel production, multi-Si wafer', 'RER', db_name=conf.technosphere)

    # Amount to recycle
    try:
        inventory_cu = panel_init.getAmount('copper, cathode')|u.kg
        #amount_glass = panel_init.getAmount('solar glass, low-iron')
    except:
        inventory_cu = panel_init.getAmount('market for copper, cathode')|u.kg
        #amount_glass = panel_init.getAmount('market for solar glass, low-iron')
        # glass commented because it is not used
    
    amount_copper = new_copper_amount + inventory_cu
    
    # Copy / update activity
    panel_adjusted = agb.copyActivity(db_name = conf.target_database,
                                      activity = panel_init,
                                      code = ACTIVITY_NAME)

    # Adding recycling related dataset
    glass_linear_density = 2.5 |(u.kg/u.millimeter)
    # 1 m**2 PV  panel has 10 kg of glass with 4 mm thickness, ref panel_init
    # FIXME : where does this value come from? not specified in original PARASOL_LCA
    elec_recycle = 20e-3/1.6 |u.t
    heat_recycle = (20e-3/1.6) / 3.6|u.t
    #FIXME check if hypotheses make sense with the "waste" activity definitions in ei3.11
    panel_adjusted.addExchanges({
        scrapAlu : conf.aluminium_frame_surfacic_weight * conf.recycling_rate_Al,
        scrapCopper : amount_copper * conf.recycling_rate_Cu,
        scrapGlass : conf.glass_thickness * glass_linear_density * (1.0 + conf.has_bifacial_modules) * conf.recycling_rate_glass,
        elec_switch_act : dict(name='elec for recycling', amount = conf.electricity_consumption_for_recycling * elec_recycle),
        heat_for_recycling : conf.heat_consumption_for_recycling * heat_recycle,
    })

    # Update the exchanges
    foil = 1.0017|u.kg
    glass_fibre = 0.18781|u.kg
    granulate = 0.37297|u.kg
    film = 0.1104|u.kg
    panel_adjusted.updateExchanges({
        'aluminium alloy, AlMg3*' : conf.aluminium_frame_surfacic_weight,
        'solar glass, low-iron*' : conf.glass_thickness * glass_linear_density * (1.0 + conf.has_bifacial_modules),
        'tempering, flat glass*' : conf.glass_thickness * glass_linear_density * (1.0 + conf.has_bifacial_modules),
        'ethylvinylacetate, foil*': foil * (1 + conf.has_bifacial_modules),
        'glass fibre reinforced plastic, polyamide, injection moulded*': glass_fibre * (1.0 - conf.has_bifacial_modules),
        'polyethylene terephthalate, granulate, amorphous*': granulate * (1.0 - conf.has_bifacial_modules),
        'polyvinylfluoride, film*': film * (1.0 - conf.has_bifacial_modules),
        'photovoltaic cell, multi-Si wafer*' : cell_adjusted,
    })

    panel_adjusted.updateExchanges({'electricity, medium voltage*': elec_switch_act})

    return panel_adjusted

# FIXME to check the single-Si hypotheses
@ensure_activity("photovoltaic panel production, single-Si wafer - adjusted")
def _ensure_pv_panel_mono_si(ACTIVITY_NAME: str, conf):
    """
    Create the PV panel manufacturing dataset and related activities.

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity
    """
    ## PV panel
    # Values
    zero = 0|u.kg
    silver_value = 9.6e-3|u.kg

    elec_switch_act = _ensure_electricity(conf)
    front_silver_amount, back_silver_amount = _metalisation_fomulae(conf)

    new_front_silver_amount = 0.84 * front_silver_amount
    new_back_silver_amount = 0.67 * back_silver_amount
    copper_amount = agb.Max(1/0.67 * 6.3e7 / 5.96e7 * ( silver_value -(new_front_silver_amount + new_back_silver_amount)), zero)
    new_copper_amount = 0.67 * copper_amount |u.kg
    # ## PV panel

    cell_adjusted = _ensure_pv_cell_manufacturing_single_si(conf)

    # +
    #Ecoinvent version
    scrapAlu = agb.findActivity('market for aluminium scrap, new', 'RER', db_name=conf.technosphere) if conf.version in {'3.11'} \
    else agb.findActivity('market for scrap aluminium*', 'Europe without Switzerland', db_name=conf.technosphere) 
        
    # Activities
    scrapGlass = agb.findActivity('market for waste glass sheet', 'Europe without Switzerland', db_name=conf.technosphere)
    scrapCopper = agb.findActivity("copper scrap, sorted, pressed, Recycled Content cut-off", db_name=conf.technosphere) if conf.version in {'3.11'} \
        else agb.findActivity('market for scrap copper*', 'Europe without Switzerland', db_name=conf.technosphere)
    heat_for_recycling = agb.findActivity('heat and power co-generation, biogas, gas engine',
                                         loc = 'RoW', unit = 'megajoule', db_name=conf.technosphere)

    # Base activity
    panel_init = agb.findActivity('photovoltaic panel production, single-Si wafer', 'RER', db_name=conf.technosphere)

    # Amount to recycle
    try:
        inventory_cu = panel_init.getAmount('copper, cathode') |u.kg
        #amount_glass = panel_init.getAmount('solar glass, low-iron')
    except:
        inventory_cu = panel_init.getAmount('market for copper, cathode') |u.kg
        #amount_glass = panel_init.getAmount('market for solar glass, low-iron')
        # glass commented because it is not used
        
    amount_copper = new_copper_amount + inventory_cu

    # Copy / update activity
    panel_adjusted = agb.copyActivity(db_name = conf.target_database,
                                      activity = panel_init,
                                      code = ACTIVITY_NAME)

    # Adding recycling related dataset
    glass_linear_density = 2.5 |(u.kg/u.millimeter)
    # 1 m**2 PV  panel has 10 kg of glass with 4 mm thickness, ref panel_init
    # FIXME : where does this value come from? not specified in original PARASOL_LCA
    elec_recycle = 20e-3/1.6 |u.t
    heat_recycle = (20e-3/1.6) / 3.6|u.t
    panel_adjusted.addExchanges({
        #Do these hypotheses work?
        scrapAlu : conf.aluminium_frame_surfacic_weight * conf.recycling_rate_Al,
        scrapCopper : amount_copper * conf.recycling_rate_Cu,
        scrapGlass : conf.glass_thickness * glass_linear_density * (1.0 + conf.has_bifacial_modules) * conf.recycling_rate_glass,
        elec_switch_act : dict(name='elec for recycling', amount = conf.electricity_consumption_for_recycling * elec_recycle),
        heat_for_recycling : conf.heat_consumption_for_recycling * heat_recycle,
    })

    # Update the exchanges
    foil = 1.0017|u.kg
    glass_fibre = 0.18781|u.kg
    granulate = 0.37297|u.kg
    film = 0.1104|u.kg
    panel_adjusted.updateExchanges({
        'aluminium alloy, AlMg3*' : conf.aluminium_frame_surfacic_weight,
        'solar glass, low-iron*' : conf.glass_thickness * glass_linear_density * (1.0 + conf.has_bifacial_modules),
        'tempering, flat glass*' : conf.glass_thickness * glass_linear_density * (1.0 + conf.has_bifacial_modules),
        'ethylvinylacetate, foil*': foil * (1 + conf.has_bifacial_modules),
        'glass fibre reinforced plastic, polyamide, injection moulded*':glass_fibre * (1.0 - conf.has_bifacial_modules),
        'polyethylene terephthalate, granulate, amorphous*':granulate * (1.0 - conf.has_bifacial_modules),
        'polyvinylfluoride, film*':film * (1.0 - conf.has_bifacial_modules),
        'photovoltaic cell, single-Si wafer*' : cell_adjusted,
    })

    panel_adjusted.updateExchanges({'electricity, medium voltage*': elec_switch_act})

    return panel_adjusted


@ensure_activity("Full PV system")
def _ensure_pv_system(ACTIVITY_NAME: str, conf):
    """Creates the PV system dataset and related activities.
    It is composed of the mounting system, electrical installation, inverter,
    PV panel, and transport-related activities.

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    Brightway activity
    """
    mounting_system = _ensure_mounting(conf)
    elec_install = _ensure_electrical_installation(conf)
    inverter_per_kg = _ensure_inverter(conf)
    panel_multi_si_adjusted = _ensure_pv_panel_multi_si(conf)
    panel_mono_si_adjusted = _ensure_pv_panel_mono_si(conf)

    panel_technology_switch = agb.newSwitchAct(
        name=f"{conf.prefix}photovoltaic panel production, wafer switch - adjusted",
        dbname = conf.target_database,
        paramDef = conf.module_pv_technology,
        acts_dict = {
            'monoSi': panel_mono_si_adjusted,
            'multiSi': panel_multi_si_adjusted,
            'polySi' : panel_multi_si_adjusted,
            'singleSi': panel_mono_si_adjusted
        }
    )


    # ## PV system

    # Tech datasets
    diesel = agb.findActivity('market for diesel, burned in building machine', "GLO", db_name=conf.technosphere)

    # Transport datasets
    transport_car = agb.findActivity('transport, passenger, car, petrol, large size, EURO 5', 'RER', db_name=conf.technosphere) if conf.version in {'3.11'}\
        else agb.findActivity('transport, passenger car, large size, petrol, EURO 5', 'RER', db_name=conf.technosphere)
    transport_van = agb.findActivity('transport, freight, light commercial vehicle, fleet average', 'Europe without Switzerland', db_name=conf.technosphere) if conf.version in {'3.11'}\
        else agb.findActivity('transport, freight, light commercial vehicle', 'Europe without Switzerland', db_name=conf.technosphere)
    
    transport_lorry = agb.findActivity('transport, freight, lorry, all sizes, EURO 6*', 'RER', db_name=conf.technosphere) if conf.version in {'3.11'} \
        else agb.findActivity('lorry, all sizes, EURO6*', 'RER', db_name=conf.technosphere)
    transport_train = agb.findActivity('transport, freight, train, electric', 'RoW', db_name=conf.technosphere) if conf.version in {'3.11'}\
        else agb.findActivity('transport, freight train, electricity', 'RoW', db_name=conf.technosphere)
    transport_sea = agb.findActivity('market for transport, freight, sea, container ship, heavy fuel oil', db_name=conf.technosphere) if conf.version in {'3.11'}\
        else agb.findActivity('market for transport, freight, sea, container ship', db_name=conf.technosphere)
    # -

    is_ground_system = 1.0 - conf.roof_vs_ground_ratio
    surface_module = 1.6 | (u.m**2) #Module surface in m²
    P_module = conf.pv_module_efficiency
    surface  = conf.power_plant_installed_capacity / P_module #total surface of the installation

    system_PV = agb.newActivity(db_name = conf.target_database,
                                name = ACTIVITY_NAME,
                                unit = "unit")

    inverter_weight = conf.inverter_weight_per_kW * conf.power_plant_installed_capacity * conf.inverter_installed_capacity_ratio
    elec_install_weight = conf.electrical_installation_specific_weight * conf.power_plant_installed_capacity


    # PV panel weigths 20kg/m²
    weightPV = 20 | (u.kg/(u.m**2))
    van_km = 100 | u.km
    inverter_weight_tonne = inverter_weight.to('tonne')
    diesel_MJ = 7673.0|u.megajoule
    diesel_kwh = 570.0|u.kilowatt
    TRANSPORT_CAR = 300 | u.km
    TRANSPORT_VAN = inverter_weight_tonne * van_km * conf.power_plant_lifetime / conf.inverter_lifetime 
    
    # Original equation from PARASOL_LCA : looks wrong
    #  total_mass_tons = 1e-3 * ((surface / surface_module) * 20\
    #                 + elec_install_weight + inverter_weight * conf.power_plant_lifetime / conf.inverter_lifetime)

    # FIXME : verify this value + hypothesis
    # Comment : the hypothesis PV panel weigths 20kg/m² suggests the total surface should be
    # multiplied by this specific weight but the surface/surface_module*weightPV 
    # suggests that this weight is per panel... meaning the unit is 20kg/unit... but that doesn't make sense, or does it?
    # for now we leave the original with
    weightPV = 20 | u.kg #per panel
    total_mass = ((surface / surface_module) * weightPV+ elec_install_weight \
                       + inverter_weight * conf.power_plant_lifetime / conf.inverter_lifetime)
    total_mass_tons = total_mass.to('tonne')

    system_PV.addExchanges({
        mounting_system : surface, #m²

        # Adding diesel burned in machine for site preparation
        # 7673 MJ were accounted for the 570 kWp power plant
        diesel : is_ground_system * conf.power_plant_installed_capacity/diesel_kwh * diesel_MJ,

        # Number of equivalent unit of 3kW elec install
        elec_install : elec_install_weight,

        inverter_per_kg : inverter_weight * conf.power_plant_lifetime / conf.inverter_lifetime,
        panel_technology_switch : surface,

        #for engineers for feasability study (100 - 200 km)(includes installation, and dismantlement)
        transport_car : TRANSPORT_CAR,

        #for maintenance
        transport_van : TRANSPORT_VAN,

        #transport in ton-kilometer (freight in payload-distance)
        transport_lorry : total_mass_tons * conf.transport_distance_lorry,
        transport_sea : total_mass_tons * conf.transport_distance_boat,
        transport_train : total_mass_tons * conf.transport_distance_train
    })

    return system_PV


@ensure_activity("PV impact per kWp installed")
def _ensure_impact_model_per_kWp(ACTIVITY_NAME: str, conf):
    """Create the impact model with a functional unit of having an installed
    capacity of 1 kWp

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    impact_per_kWp : Brightway2 / lca_algebraic activity with the impact model

    """
    # ## per kWp
    system_PV = _ensure_pv_system(conf)

    # Impact model, per kWp
    impact_per_kWp = agb.newActivity(
        db_name = conf.target_database,
        name = ACTIVITY_NAME,
        unit = "kilowatt",
        exchanges = {
            system_PV : 1.0 / conf.power_plant_installed_capacity
        })

    return impact_per_kWp


@ensure_activity("PV impact per kWh")
def _ensure_impact_model_per_kWh(ACTIVITY_NAME: str, conf):
    """Create the impact model with a functional unit of the production of
    1 kWh of electricity

    Parameters
    ----------
    conf: ParasolLCA
        see. help(ParasolLCA)

    Returns
    -------
    impact_per_kWh : Brightway2 / lca_algebraic activity with the impact model

    """
    # ## per kWh
    system_PV = _ensure_pv_system(conf)
    impact_per_kWh = agb.newActivity(
        db_name = conf.target_database,
        name = ACTIVITY_NAME,
        unit = "kWh",
        exchanges = {system_PV : 1.0 / (conf.power_plant_installed_capacity*conf.power_plant_lifetime * conf.normalised_annual_PV_production_kWh_per_kWp)})

    return impact_per_kWh


