示例#1
0
class udb_reactor(Facility):

    reactor_id = ts.Int(
        doc=
        "This variable lists the reactor id of the reactors in the database ",
        tooltip="Reactor Id in database",
        uilabel="Reactor ID")

    outcommod = ts.String(doc="The commodity this institution will output",
                          tooltip="Output commodity",
                          uilabel="Output Commodity")

    inventory = ts.ResBufMaterialInv()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def write(self, string):
        with open('log.txt', 'a') as f:
            f.write(string + '\n')

    def tock(self):
        self.write('what')

        # Example dummy code
        composition = {922350000: 5, 922380000: 95}
        material = ts.Material.create(self, 100, composition)

        self.inventory.push(material)
        self.write(str(self.inventory.quantity))

    #     time = self.context.time
    #     get rows that match with current time

    #     for information in rows:
    #         Create material given by recipe and quantity
    #         composition = {ZZAAA0000: massfrac,
    #                        ZZAAA0000: massfrac}
    #         recipe = self.context.get_recipe()
    #         material = ts.Material.create(self, quantity, recipe)

    #         Push material to out buffer
    #         self.out.push(material)

    def get_material_bids(self, requests):
        if self.outcommod not in requests:
            return
        reqs = requests[self.outcommod]
        bids = [reqs]
        ports = [{"bids": bids, "constraints": self.inventory.quantity}]
        return ports

    def get_material_trades(self, trades):
        responses = {}
        for trade in trades:
            print(trade)
            mat = self.inventory.pop()
            responses[trade] = mat
        return responses
示例#2
0
class Reactor(Facility):
    """
    A reactor model that requests fuel early such that it will recieve fuel in time for
    operation.  
    """

    request_lead_time = ts.Double(
        doc="The number of time steps before refuel that the reactor will request fuel.", 
        tooltip="The number of time steps before refuel that the reactor will request fuel.",
        uilabel="Request Lead Time"
    )

    commodity = ts.String(
        doc="The commodity that the reactor desires", 
        tooltip="Reactor Commodity",
        uilabel="Commodity"
    )

    cycle_length = ts.Double(
        doc="The amount of time steps between reactor refuels", 
        tooltip="Cycle length of the reactor.",
        uilabel="Cycle Length"
    )
    
    recipe = ts.String(
        doc="Recipe", 
        tooltip="Recipe",
        uilabel="Recipe"
    )

    fuel_mass = ts.Double(
        doc="Mass of requested fuel", 
        tooltip="Mass of Batch",
        uilabel="Fuel Mass"
    )


    fresh_fuel = ts.ResBufMaterialInv(capacity=1000.)
    core = ts.ResBufMaterialInv(capacity=1000.)
    waste = ts.ResBufMaterialInv()
    

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.rx_time = 0;
        self.ct_time = -2;        

    def tick(self):
        #print(self.id, self.fresh_fuel.count, self.core.count, self.waste.count)
        if self.rx_time == self.cycle_length:
            self.waste.push(self.core.pop())
            self.core.push(self.fresh_fuel.pop())
        elif self.rx_time < self.cycle_length:
            self.rx_time += 1
            self.ct_time += 1

    def get_material_requests(self):
        ports = []
        if self.fresh_fuel.count == 0:
            #print(str(self.id) + " is requesting fuel")
            request_qty = self.fuel_mass
            recipe_a = self.context.get_recipe(self.recipe)
            target_a = ts.Material.create_untracked(request_qty, recipe_a)
            commods = {self.commodity: target_a}
            port = {"commodities": commods, "constraints": request_qty}
            ports.append(port)
        if self.ct_time == self.cycle_length-self.request_lead_time or self.ct_time == -1:
            #print(str(self.id) + " requesting contract")
            request_qty = self.fuel_mass
            recipe_a = self.context.get_recipe(self.recipe)
            target_a = ts.Material.create_untracked(request_qty, recipe_a)
            commods = {self.commodity+"-contract": target_a}
            port = {"commodities": commods, "constraints": request_qty}
            ports.append(port)
        return ports

    def accept_material_trades(self, responses):
        for mat in responses.values():
            if self.core.count == 0:
                self.core.push(mat)
            else:
                self.fresh_fuel.push(mat)
            self.rx_time = 0
            self.ct_time = 0
示例#3
0
文件: ann_lwr.py 项目: jbae11/ann_pwr
class ann_lwr(Facility):
    fuel_incommod = ts.String(
        doc="The commodity name for incoming fuel",
        tooltip="Incoming fuel",
        uilabel="Incoming fuel"
    )

    fuel_outcommod = ts.String(
        doc="The commodity name for discharge fuel",
        tooltip="Discharge Fuel",
        uilabel="Discharge Fuel"
    )

    pickle_path = ts.String(
        doc="Path to the pickle file",
        tooltip="Absolute path to the pickle file"
    )

    # one row would be 2.1_30000 3.1_40000 4.1_50000 etc
    enr_bu_matrix = ts.VectorString(
        doc="enrichment and burnup matrix",
        tooltip="enrichment_burnup column separated by space"
    )

    n_assem_core = ts.Int(
        doc="Number of assemblies",
        tooltip="Number of assemblies in core"
    )

    n_assem_batch = ts.Int(
        doc="Number of assemblies per batch",
        tooltip="Number of assemblies per batch"
    )

    assem_size = ts.Double(
        doc="Assembly mass",
        tooltip="Assembly mass"
    )

    power_cap = ts.Double(
        doc="Power capacity of reactor",
        tooltip="Power capacity of reactor",
    )

    cycle_time_eq = ts.String(
        doc="cycle time of reactor equation",
        tooltip="Cycle time of reactor equation"
    )

    refuel_time_eq = ts.String(
        doc="Refuel time of reactor equation",
        tooltip="Refuel time of reactor equation"
    )

    core = ts.ResBufMaterialInv()
    waste = ts.ResBufMaterialInv()


    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def enter_notify(self):
        super().enter_notify()
        self.model_dict = pickle.load(open(self.pickle_path, 'rb'))
        # change other to h-1
        other_index = self.model_dict['iso_list'].index('other')
        self.model_dict['iso_list'][other_index] = 'h-1'
        self.iso_list = self.model_dict['iso_list']

        # check if it's integer batches
        if (self.n_assem_core / self.n_assem_batch)%1 != 0:
            raise ValueError('Sorry can only do integer batches')

        # input consistency checking
        self.enr_matrix, self.bu_matrix = self.check_enr_bu_matrix()

        # !!
        self.f = open('f.txt', 'w')
        # set initial cycle and refuel time
        t = self.context.time
        self.cycle_time = max(0, int(eval(self.cycle_time_eq)))
        self.refuel_time = max(0, int(eval(self.refuel_time_eq)))

        # set core capacity
        self.core.capacity = self.n_assem_core * self.assem_size

        self.cycle_step = 0
        self.batch_gen = 0
        self.n_batch = int(self.n_assem_core / self.n_assem_batch)
        # if no exit time, exit time is 1e5
        if self.exit_time == -1:
            self.decom_time = 1e5
        else:
            self.decom_time = self.exit_time

    def tick(self):
        # If time to decommission, where if decommissioning
        # mid cycle, deplete using weighted average
        # and discharge
        if self.context.time == self.decom_time:
            # burnup is prorated by the ratio
            cycle_step_ratio = self.cycle_step / self.cycle_time
            for index, bu_list in enumerate(self.bu_matrix):
                prorated_bu_list = bu_list * cycle_step_ratio
                self.transmute_and_discharge(prorated_bu_list,
                                             self.enr_matrix[index])
            return

        if self.cycle_step == self.cycle_time:
            if self.batch_gen < self.n_batch:
                i = self.batch_gen
            else:
                i = -1
            bu_list = self.bu_matrix[i]
            self.transmute_and_discharge(bu_list,
                                         self.enr_matrix[i])
            self.batch_gen += 1


    def tock(self):
        if (self.cycle_step >= self.cycle_time + self.refuel_time) and (self.is_core_full()):
            t = self.context.time
            self.cycle_time = max(0, int(eval(self.cycle_time_eq)))
            self.refuel_time = max(0, int(eval(self.refuel_time_eq)))
            self.cycle_step = 1

        # produce power if core is full
        if (self.cycle_step >= 0) and (self.cycle_step < self.cycle_time) and (self.is_core_full()):
            self.produce_power(True)
        else:
            self.produce_power(False)

        if self.cycle_step > 0 or self.is_core_full():
            self.cycle_step += 1


    def get_material_bids(self, requests):
        """ Gets material bids that want its 'outcommod' and
            returns bid portfolio
        """
        bids = []
        if self.fuel_outcommod in requests.keys():
            reqs = requests[self.fuel_outcommod]
            for req in reqs:
                if self.waste.empty():
                    break
                qty = min(req.target.quantity, self.waste.quantity
                        )
                next_in_line = self.waste.peek()
                mat = ts.Material.create_untracked(qty, next_in_line.comp())
                bids.append({'request': req, 'offer': mat})
        if len(bids) == 0:
            return
        port = {'bids': bids}
        return port

    def get_material_trades(self, trades):
        """ Give out fuel_outcommod from waste buffer"""
        responses = {}
        for trade in trades:
            commodity = trade.request.commodity
            if commodity == self.fuel_outcommod:
                mat_list = self.waste.pop_n(self.waste.count)
            if len(mat_list) > 1:
                for mat in mat_list[1:]:
                    mat_list[0].absorb(mat)
            responses[trade] = mat_list[0]
        return responses

    def get_material_requests(self):
        """ Ask for fuel_incommod"""
        ports = []
        if self.context.time == self.decom_time:
            return []
        if self.is_core_full():
            return []

        recipes = {}
        qty = {}
        mat = {}
        t = self.context.time
        # initial core loading
        if self.batch_gen == 0:
            enr_to_request = self.enr_matrix
            for i in range(np.shape(enr_to_request)[0]):
                for j in range(np.shape(enr_to_request)[1]):
                    enr = eval(enr_to_request[i,j])
                    comp = {'u-238': 100-enr,
                            'u-235': enr}
                    qty = self.assem_size
                    mat = ts.Material.create_untracked(qty, comp)

                    ports.append({'commodities': {self.fuel_incommod: mat},
                                  'constraints': qty})
        # subsequent equilibrium batch loading
        else:
            enr_to_request = self.enr_matrix[-1]
            for enrichment in enr_to_request:
                enr = eval(enrichment)
                comp = {'u-238': 100-enr,
                        'u-235': enr}
                qty = self.assem_size
                mat = ts.Material.create_untracked(qty, comp)
                ports.append({'commodities' : {self.fuel_incommod: mat},
                              'constraints': qty})

        return ports


    def accept_material_trades(self, responses):
        """ Get fuel_incommod and store it into core"""
        for key, mat in responses.items():
            if key.request.commodity == self.fuel_incommod:
                self.core.push(mat)


    def is_core_full(self):
        if self.core.count == self.n_assem_core:
            return True
        else:
            return False


    def predict(self, enr_bu):
        model = self.model_dict['model']
        x = self.model_dict['xscaler'].transform(enr_bu)
        y = self.model_dict['yscaler'].inverse_transform(
                model.predict(x))[0]
        comp_dict = {}
        for indx, iso in enumerate(self.iso_list):
            # zero if model predicts negative
            if y[indx] < 0:
                y[indx] = 0
            comp_dict[iso] = y[indx]
        return comp_dict


    def transmute_and_discharge(self, bu_list, enr_list):
        # this should ideally be one batch,
        t = self.context.time
        if self.batch_gen < self.n_batch:
           enr = enr_list[self.batch_gen]
        else:
            enr = enr_list[-1]
        for indx, bu in enumerate(bu_list):
            enr_bu = [[eval(enr_list[indx]),eval(bu)]]
            print('Transmuting fuel with enrichment, burnup:')
            print(enr_bu)
            discharge_fuel = self.core.pop()
            comp = self.predict(enr_bu)
            discharge_fuel.transmute(comp)
            self.waste.push(discharge_fuel)


    def produce_power(self, produce=True):
        if produce:
            lib.record_time_series(lib.POWER, self, float(self.power_cap))
        else:
            lib.record_time_series(lib.POWER, self, 0)


    def check_enr_bu_matrix(self):
        # parse bu enr matrix
        empty = np.zeros(len(self.enr_bu_matrix[0].split(' ')))

        for i in self.enr_bu_matrix:
            entry = np.array(i.split(' '))
            if len(entry) != self.n_assem_batch:
                raise ValueError('The length of entry has to match n_assem_batch')
            try:
                empty = np.vstack((empty, entry))
            except ValueError:
                print('Your length of entries per batch are inconsistent!')
        matrix = empty[1:]

        # separate bu and enrichment
        sep = np.char.split(matrix, '_')
        bu_matrix = np.empty(np.shape(matrix), dtype=object)
        enr_matrix = np.empty(np.shape(matrix), dtype=object)
        for i in range(np.shape(sep)[0]):
            for j in range(np.shape(sep)[1]):
                enr_matrix[i,j] = sep[i,j][0]
                bu_matrix[i,j] = sep[i,j][1]

        return enr_matrix, bu_matrix
示例#4
0
class udb_reactor(Facility):

    reactor_id = ts.Int(
        doc="This variable lists the reactor id of the reactors in the database ",
        tooltip="Reactor Id in database",
        uilabel="Reactor ID"
    )

    outcommod = ts.String(
        doc="The commodity this institution will output",
        tooltip="Output commodity",
        uilabel="Output Commodity"
    )

    db_path = ts.String(
        doc="Path to the sqlite file of udb data",
        tooltip="Absolute path to the udb sqlite data"
    )

    recipe_name = ts.String(
        doc="if using recipe, this parameter holds the recipe name",
        tooltip="recipe to be used for recipe composition",
        default=''
    )

    startyear = ts.Int(
        doc="Startyear of simulation",
        tooltip="Simulation Startyear"
    )

    startmonth = ts.Int(
        doc="Startmonth of simulation",
        tooltip="Simulation Startmonth"
    )

    use_rom = ts.Bool(
        doc="Boolean to use reduced-order-model for depletion"
        tooltip="ROM bool"
        default=0
    )

    inventory = ts.ResBufMaterialInv()

    ## Import pickle file into `depletion_model_dict'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def write(self, string):
        # for debugging purposes.
        with open('log.txt', 'a+') as f:
            f.write(string + '\n')

    def enter_notify(self):
        super().enter_notify()
        df = pd.read_table(self.db_path)
        self.reactor_assems = df.loc[df['reactor_id'] == self.reactor_id]
        self.reactor_assems['discharge_date'] = self.reactor_assems['discharge_date'].str[:7]
        self.assembly_dates = self.reactor_assems['discharge_date'].unique()
        # for memory
        del df

    def tick(self):
        year_month = self.find_year_month()
        if year_month in self.assembly_dates:
            assembly_id_list = self.reactor_assems.loc[self.reactor_assems['discharge_date'] == year_month]['assembly_id'].unique()

            for assembly in assembly_id_list:
                assem_mass = np.array(
                    self.reactor_assems.loc[self.reactor_assems['assembly_id'] == assembly_id]['initial_uranium_kg'])[0]
                if self.recipe_name != '':
                    composition = self.context.get_recipe(self.recipe_name)
                elif use_rom:
                    composition = self.rom_depletion(assembly)
                else:
                    composition = self.data_depletion(assembly)

                material = ts.Material.create(self, assem_mass, composition)
                self.inventory.push(material)


    def get_material_bids(self, requests):
        """ Gets material bids that want its `outcommod' an
            returns bid portfolio
        """
        if self.outcommod not in requests:
            return
        reqs = requests[self.outcommod]
        bids = []
        for req in reqs:
            qty = min(req.target.quantity, self.inventory.quantity)
            # returns if the inventory is empty
            if self.inventory.empty():
                return
            # get the composition of the material next in line
            next_in_line = self.inventory.peek()
            mat = ts.Material.create_untracked(qty, next_in_line.comp())
            bids.append({'request': req, 'offer': mat})
        port = {"bids": bids}
        return port


    def get_material_trades(self, trades):
        responses = {}
        for trade in trades:
            mat_list = self.inventory.pop_n(self.inventory.count)
            # absorb all materials
            # best way is to do it separately, but idk how to do it :(
            for mat in mat_list[1:]:
                mat_list[0].absorb(mat)
            responses[trade] = mat_list[0]
        return responses

    def find_year_month(self):
        time = self.context.time
        year = self.startyear + time // 12
        month = self.startmonth + time % 12
        if month < 10:
            return (str(year) + '-0' + str(month))
        else:
            return (str(year) + '-' + str(month))

    def rom_depletion(self, assembly_id):
        enr_bu = self.reactor_assems.loc[self.reactor_assems['assembly_id'] == assembly_id][[
            'initial_enrichment', 'discharge_burnup']]
        enr_bu = np.array(enr_bu)[0]
        
        composition = {}
        for iso, model in self.depletion_model_dict.items():
            composition[iso] = model.predict(enr_bu)[0]

    def data_depletion(self, assembly_id):
        assem_data = self.reactor_assems.loc[self.reactor_assems['assembly_id'] == assembly_id][['name', 'total_mass_g']]
        assem_data['comp'] = assem_data['total_mass_g'] / sum(assem_data['total_mass_g'])
        composition = {}
        for indx, row in assem_data.iterrows():
            composition[row['name']] = row['comp']
        return composition
示例#5
0
class Truck(Facility):
    """
    A truck that transports material through the fuel cycle.
    """

    dest_commodity = ts.String(
        doc="The commodity that the truck carries",
        tooltip="Shipped Commodity",
        uilabel="Commodity"
    )

    source_commodity = ts.String(
        doc="The commodity that the truck carries",
        tooltip="Shipped Commodity",
        uilabel="Commodity"
    )

    contract = ts.PairDoubleMapIntDouble(
        doc="The contract quantity and recipe",
        tooltip="Contract quantity and recipe",
        uilabel="Contract",
        default=(0.0,{})
    )

    contractee = ts.Int(
        doc="The reactor that originates the contract with the truck (agentID)",
        tooltip="Reactor generating the contract",
        uilabel="Contractee",
        default=-1
    )

    total_trip_duration = ts.Int(
        doc="The reactor that originates the contract with the truck (agentID)",
        tooltip="Reactor generating the contract",
        uilabel="Contractee"
    )

    trip_time = ts.Int(
        doc="The reactor that originates the contract with the truck (agentID)",
        tooltip="Reactor generating the contract",
        uilabel="Contractee",
        default=-1
    )

    return_trip_time = ts.Int(
        doc="The reactor that originates the contract with the truck (agentID)",
        tooltip="Reactor generating the contract",
        uilabel="Contractee",
        default=-1
    )

    capacity = ts.Double(
        doc="The reactor that originates the contract with the truck (agentID)",
        tooltip="Reactor generating the contract",
        uilabel="Contractee",
    )

    inventory = ts.ResBufMaterialInv()


    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.inventory.capacity = self.capacity
    
    def tock(self):
        #print("Truck: " + str(self.id) + " " + str(self.inventory.count))
        #print(self.return_trip_time, self.trip_time, self.total_trip_duration)
        if self.return_trip_time >= 0:
            self.return_trip_time += 1
        if self.return_trip_time == self.total_trip_duration:
            self.return_trip_time = -1
            return
        elif self.trip_time >= 0 and self.trip_time < self.total_trip_duration:
            self.trip_time += 1

    def get_material_requests(self):
        if self.return_trip_time >= 0:
            return []
        if self.contractee > -1 and self.inventory.count == 0:
            #requestfuel
            target_a = ts.Material.create_untracked(self.contract[0], self.contract[1])
            commods = {self.source_commodity: target_a}
            port = {"commodities": commods, "constraints": self.capacity}
            #print(str(self.id) + " is attempting to pick up fresh fuel")
            return [port]
        else:
            return []

    def get_material_bids(self, requests):
        if self.return_trip_time >= 0:
            return
        ports = []
        if self.dest_commodity not in requests and self.dest_commodity+"-contract" not in requests:
            return
        if self.contractee == -1 and self.inventory.count == 0:
            #print(str(self.id) + " is accepting contracts")
            #offercontract
            if self.dest_commodity+"-contract" in requests:
                reqs = requests[self.dest_commodity+"-contract"]
                bids = list(reqs)
                ports.append({"bids": bids, "constraints": self.capacity})
                return ports
        elif self.contractee > -1 and self.inventory.count > 0 and self.trip_time == self.total_trip_duration:
            #offerfuel
            bid = ""
            reqs = requests[self.dest_commodity]
            for req in reqs:
                if req.requester.id == self.contractee:
                    bid = req
                    break
            bids = [bid]
            ports.append({"bids": bids, "constraints": self.capacity})
            return ports
        else:
            return ports

    def get_material_trades(self, trades):
        responses = {}
        if self.return_trip_time >= 0:
            return responses
        if self.contractee == -1 and self.inventory.count == 0:
            #offercontract
            for trade in trades:
                self.contract = (trade.amt, trade.request.target.comp())
                self.contractee = trade.request.requester.id
                #print(str(self.id) + " is accepting a contract from " + str(self.contractee))
        elif self.contractee > -1 and self.inventory.count > 0 and self.trip_time == self.total_trip_duration:
            #offerfuel
            for trade in trades:
                mat = self.inventory.pop()
                responses[trade] = mat
            #print(str(self.id) + " is dropping off fuel at " + str(self.contractee))
            self.return_trip_time = 0
            self.contract = (-1, {})
            self.contractee = -1
        return responses

    def accept_material_trades(self, responses):
        if self.return_trip_time >= 0:
            return
        for mat in responses.values():
            self.inventory.push(mat)
            self.trip_time = 0
示例#6
0
class saltproc_reactor(Facility):
    """
    This reactor imports an HDF5 file from a saltproc run (or a converted SCALE output).
    It imports the following data:
        surplus fissile output composition and isotopics in time
        waste output isotopics in time
        fertile input isotopics in time
        core isotopics in time
        blanket isotopics(if applicable)
    """
    init_fuel_commod = ts.String(
        doc="The commodity name for initial loading fuel",
        tooltip="Init Fuel",
        uilabel="Init Fuel")

    final_fuel_commod = ts.String(
        doc="The commodity name for final discharge fuel",
        tooltip="Final Fuel",
        uilabel="Final Fuel")

    fill_commod = ts.String(
        doc="The commodity this facility will take in for fertile materials ",
        tooltip="Fill Commodity",
        uilabel="Fill Commodity")

    fissile_out_commod = ts.String(
        doc="The fissile commodity this facility will output",
        tooltip="Fissile commodity",
        uilabel="Fissile Commodity")

    waste_commod = ts.String(
        doc="The waste commodity this facility will output",
        tooltip="Waste commodity",
        uilabel="Waste Commodity")

    db_path = ts.String(doc="Path to the hdf5 file",
                        tooltip="Absolute path to the hdf5 file")

    power_cap = ts.Float(doc="Power capacity of reactor",
                         tooltip="Power Capacity")

    waste_tank = ts.ResBufMaterialInv()
    fissile_tank = ts.ResBufMaterialInv()

    driver_buf = ts.ResBufMaterialInv()
    blanket_buf = ts.ResBufMaterialInv()

    fill_tank = ts.ResBufMaterialInv()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def enter_notify(self):
        super().enter_notify()
        self.f = h5py.File(self.db_path, 'r')
        self.max_nonzero_indx = self.get_max_nonzero_indx()
        # subject to change
        self.isos = self.f['iso names']
        self.num_isotopes = len(self.isos)
        self.waste_db = self.cum_to_nocum(self.f['waste tank composition'])
        self.fissile_db = self.cum_to_nocum(self.f['fissile tank composition'])
        self.driver_refill = self.cum_to_nocum(
            self.f['driver refill tank composition'])
        self.blanket_refill = self.cum_to_nocum(
            self.f['blanket refill tank composition'])
        self.driver_db = self.cutoff_nonzero(
            self.f['driver composition after reproc'])
        self.blanket_db = self.cutoff_nonzero(
            self.f['blanket composition after reproc'])

        self.siminfo_timestep = int(
            self.f['siminfo_timestep'][()].decode('utf-8'))
        self.saltproc_timestep = self.siminfo_timestep * 24 * 3600
        self.buf_dict = {
            'driver': self.driver_buf,
            'blanket': self.blanket_buf
        }
        self.prev_indx = 0
        self.driver_mass = sum(self.driver_db[0])
        self.blanket_mass = sum(self.blanket_db[0])
        self.driver_buf.capacity = self.driver_mass
        if self.blanket_mass == 0:
            self.blanket_buf.capacity = 0
            del self.buf_dict['blanket']
        else:
            self.blanket_buf.capacity = self.blanket_mass
        self.fresh = True
        self.loaded = False
        self.shutdown = False

    def cum_to_nocum(self, dataset):
        """ Convert cumulative array to non-cumulative array
        Parameters:
        -----------
        dataset: hdf5 dataset
        """
        new_array = np.zeros((self.max_nonzero_indx, self.num_isotopes))
        new_array[0] = dataset[0]
        for i in range(1, self.max_nonzero_indx):
            new_array[i] = dataset[i] - dataset[i - 1]
        return new_array

    def cutoff_nonzero(self, dataset):
        return dataset[:self.max_nonzero_indx]

    def get_max_nonzero_indx(self):
        self.tot_timesteps = len(self.f['driver composition after reproc'])
        for i in range(self.tot_timesteps):
            if sum(self.f['driver composition after reproc'][i]) == 0:
                return i - 1
        return self.tot_timesteps

    def tick(self):
        if not self.fresh:
            reactor_age_sec = self.context.dt * \
                (self.context.time - self.start_time)
            timestep_at_hdf5 = int(reactor_age_sec / self.saltproc_timestep)
            if timestep_at_hdf5 < len(self.waste_db):
                self.indx = timestep_at_hdf5
            else:
                self.indx = self.indx_tuple[1]
                self.prev_indx = self.indx_tuple[0]
        else:
            self.indx = -1
        # if reactor is `on'
        if self.indx > 0:
            # push waste from db to waste_tank
            self.get_waste()
            # push fissile from db to fissile_tank
            self.get_fissile()
            self.get_fill_demand()
            self.indx_tuple = (self.prev_indx, self.indx)
            self.prev_indx = self.indx + 1

    def check_core_full(self):
        for key, val in self.buf_dict.items():
            if (val.capacity - val.quantity) > 1:
                return False
        return True

    def tock(self):
        # check if core is full;
        if self.check_core_full():
            self.loaded = True
            self.produce_power()
            if self.fresh:
                self.start_time = self.context.time
                self.fresh = False
        elif self.context.time != self.exit_time:
            self.loaded = False
            self.produce_power(False)

    def get_waste(self):
        waste_dump = np.zeros(self.num_isotopes)
        waste_comp = {}
        # lump all the waste generated in this timestep
        # into one waste dump
        for t in np.arange(self.prev_indx, self.indx + 1):
            waste_dump += self.waste_db[t, :]
        # convert this into a dictionary

        waste_mass = sum(waste_dump)
        waste_comp = self.array_to_comp_dict(waste_dump)
        if waste_mass != 0:
            material = ts.Material.create(self, waste_mass, waste_comp)
            self.waste_tank.push(material)

    def get_fissile(self):
        fissile_dump = np.zeros(self.num_isotopes)
        fissile_comp = {}

        for t in np.arange(self.prev_indx, self.indx + 1):
            fissile_dump += self.fissile_db[t, :]

        fissile_mass = sum(fissile_dump)
        fissile_comp = self.array_to_comp_dict(fissile_dump)

        if fissile_mass != 0:
            material = ts.Material.create(self, fissile_mass, fissile_comp)
            self.fissile_tank.push(material)

    def get_fill_demand(self):
        self.get_fill = False

        demands = {}
        masses = {}
        for bufs in self.buf_dict.keys():
            demands[bufs] = np.zeros(self.num_isotopes)
        fill_comp_dict = {}
        # since the data is in negative:
        for t in np.arange(self.prev_indx, self.indx + 1):
            for key, val in demands.items():
                if 'driver' in key:
                    demands[key] += -1.0 * self.driver_refill[t, :]
                if 'blanket' in key:
                    demands[key] += -1.0 * self.blanket_refill[t, :]

        for key, val in demands.items():
            masses[key] = sum(val)

        self.qty = sum(masses.values())
        if (self.qty) == 0:
            return 0

        for key, val in self.buf_dict.items():
            val.pop(masses[key])
        self.fill_comp = sum(demands.values())

        fill_comp_dict = self.array_to_comp_dict(self.fill_comp)
        if bool(fill_comp_dict):
            self.demand_mat = ts.Material.create_untracked(
                self.qty, fill_comp_dict)
        if self.qty != 0.0:
            self.get_fill = True

    def get_material_bids(self, requests):
        """ Gets material bids that want its `outcommod' and
            returns bid portfolio
        """
        bids = []
        # waste commods
        try:
            reqs = requests[self.waste_commod]
            for req in reqs:
                qty = min(req.target.quantity, self.waste_tank.quantity)
                # returns if the inventory is empty
                if self.waste_tank.empty():
                    break
                # get the composition of the material next in line
                next_in_line = self.waste_tank.peek()
                mat = ts.Material.create_untracked(qty, next_in_line.comp())
                bids.append({'request': req, 'offer': mat})
        except KeyError:
            print('No one is requesting ', self.waste_commod)

        try:
            reqs = requests[self.fissile_out_commod]
            for req in reqs:
                qty = min(req.target.quantity, self.fissile_tank.quantity)
                if self.fissile_tank.empty():
                    break
                next_in_line = self.fissile_tank.peek()
                mat = ts.Material.create_untracked(qty, next_in_line.comp())
                bids.append({'request': req, 'offer': mat})
        except KeyError:
            print('No one is requesting ', self.fissile_out_commod)

        if self.context.time == self.exit_time:
            self.shutdown = True
            try:
                reqs = requests[self.final_fuel_commod]
                for req in reqs:
                    total_qty = self.driver_buf.quantity + self.blanket_buf.quantity
                    qty = min(req.target.quantity, total_qty)
                    if self.driver_buf.empty():
                        break
                    # driver material
                    driver_comp = self.array_to_comp_dict(
                        self.driver_db[self.indx])

                    driver_mat = ts.Material.create(self,
                                                    self.driver_buf.quantity,
                                                    driver_comp)
                    blanket_comp = self.array_to_comp_dict(
                        self.blanket_db[self.indx])
                    blanket_mat = ts.Material.create(self,
                                                     self.blanket_buf.quantity,
                                                     blanket_comp)
                    driver_mat.absorb(blanket_mat)
                    bids.append({'request': req, 'offer': driver_mat})
            except KeyError:
                print('No one is requesting ', self.final_fuel_commod)
                # postpone shutdown..?
        if len(bids) == 0:
            return
        port = {"bids": bids}
        return port

    def get_material_trades(self, trades):
        """ Give out waste_commod and fissile_out_commod from
            waste_tank and fissile_tank, respectively.
        """
        responses = {}
        for trade in trades:
            commodity = trade.request.commodity

            if commodity == self.waste_commod:
                mat_list = self.waste_tank.pop_n(self.waste_tank.count)
            if commodity == self.fissile_out_commod:
                mat_list = self.fissile_tank.pop_n(self.fissile_tank.count)
            if commodity == self.final_fuel_commod:
                blank_comp = self.array_to_comp_dict(
                    self.blanket_db[self.prev_indx, :])
                driver_comp = self.array_to_comp_dict(
                    self.driver_db[self.prev_indx, :])
                blank = ts.Material.create(self, self.blanket_mass, blank_comp)
                driv = ts.Material.create(self, self.driver_mass, driver_comp)
                driv.absorb(blank)
                mat_list = [driv]
            # absorb all materials
            # best way is to do it separately, but idk how to do it :(
            for mat in mat_list[1:]:
                mat_list[0].absorb(mat)
            responses[trade] = mat_list[0]
        return responses

    def get_material_requests(self):
        """ Ask for material fill_commod """
        ports = []
        if self.shutdown:
            return {}
        if not self.loaded:
            recipes = {}
            qty = {}
            mat = {}
            for key, val in self.buf_dict.items():
                if 'driver' in key:
                    recipes[key] = self.array_to_comp_dict(
                        self.f['siminfo_driver_init_comp'])
                if 'blanket' in key:
                    recipes[key] = self.array_to_comp_dict(
                        self.f['siminfo_blanket_init_comp'])
                qty[key] = val.capacity - val.quantity
                mat[key] = ts.Material.create_untracked(qty[key], recipes[key])

            for key, val in self.buf_dict.items():
                if 'driver' in key:
                    ports.append({
                        'commodities': {
                            self.init_fuel_commod: mat[key]
                        },
                        'constraints': qty[key]
                    })
                if 'blanket' in key:
                    ports.append({
                        'commodities': {
                            self.fill_commod: mat[key]
                        },
                        'constraints': qty[key]
                    })
            return ports
        elif self.get_fill and self.context.time != self.exit_time:
            commods = {self.fill_commod: self.demand_mat}
            port = {'commodities': commods, 'constraints': self.qty}
            return port
        return []

    def accept_material_trades(self, responses):
        """ Get fill_commod and store it into fill_tank """
        for key, mat in responses.items():
            if key.request.commodity == self.init_fuel_commod and not self.loaded:
                self.driver_buf.push(mat)
            elif key.request.commodity == self.fill_commod:
                to_blanket = mat.extract_qty(self.blanket_buf.space)
                self.blanket_buf.push(to_blanket)
                self.driver_buf.push(mat)

    def array_to_comp_dict(self, array):
        dictionary = {}
        for i, val in enumerate(array):
            if val != 0:
                iso = self.isos[i].decode('utf8')
                dictionary[iso] = val
        return dictionary

    def produce_power(self, produce=True):
        if produce:
            lib.record_time_series(lib.POWER, self, float(self.power_cap))
        else:
            lib.record_time_series(lib.POWER, self, 0)