@j.schmoelder , thanks for the response, but I fear you may have given me more questions than answers…
So I think there may be some issues in using the CarouselBuilder
vs Flowsheet
, at least in this formulation of the problem. I did update to the dev version, though.
1) I’m not sure I ever specified an eluent source? Unless eluent is somehow a protected variable name
#In's
feed = Inlet(component_system, name='feed')
feed.c = [10, 10] # M
feed.flow_rate = 2e-7 #m^3/s
eluent = Inlet(component_system, name='eluent')
eluent.c = [0, 0] # M
eluent.flow_rate = 6e-7 #m^3/s
#Outs
raffinate = Outlet(component_system, name='raffinate')
extract = Outlet(component_system, name='extract')
2) Not all attributes seem to transfer from the FlowSheet via the CarouselBuilder wrapper.
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[25], line 1
----> 1 builder.output_states
AttributeError: 'CarouselBuilder' object has no attribute 'output_states'
So I’m not sure how to access w_r
and w_e
. Adding them just as names gives a different error (see #2)
3) Using builder.eluent.flow_rate
since I didn’t use flow_sheet
optimization_problem.add_variable(
'builder.eluent.flow_rate',
lb=1e-7, ub=10e-7,
transform='auto'
)
raises an error
File ~\Anaconda3\envs\cadet\lib\site-packages\CADETProcess\optimization\optimizationProblem.py:347, in OptimizationProblem.add_variable(self, name, evaluation_objects, parameter_path, lb, ub, transform, indices)
342 if parameter_path is not None and len(evaluation_objects) == 0:
343 raise ValueError(
344 "Cannot set parameter_path for variable without evaluation object "
345 )
--> 347 var = OptimizationVariable(
348 name, evaluation_objects, parameter_path,
349 lb=lb, ub=ub, transform=transform,
350 indices=indices,
351 )
353 self._variables.append(var)
355 with warnings.catch_warnings():
CADETProcessError: Not a valid Optimization variable
Although builder.set_output_state
is not an issue in the process definition section, I just can’t seem to access the value as a variable
Adding w_r
and ```w_e`` give a similar issue
4) The use of the pre_processing
argument in add_variable
gives an unexpected keyword error
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[11], line 1
----> 1 optimization_problem.add_variable(
2 name='w_r',
3 lb=0, ub=1,
4 pre_processing=lambda x: [x[0], 1 - x[0]],
5 )
6 optimization_problem.add_variable(
7 name='w_e',
8 lb=0, ub=1,
9 )
TypeError: add_variable() got an unexpected keyword argument 'pre_processing
Adding the whole script for reference, in case I’m omitting anything important
# System Definition
from CADETProcess.processModel import ComponentSystem
from CADETProcess.processModel import Linear, Langmuir
from CADETProcess.processModel import LumpedRateModelWithoutPores
from CADETProcess.processModel import Inlet, Outlet
from CADETProcess.modelBuilder import SerialZone, ParallelZone, CarouselBuilder
from CADETProcess.simulator import Cadet
from CADETProcess.stationarity import StationarityEvaluator
from CADETProcess.stationarity import RelativeArea
from CADETProcess.processModel import Linear
from CADETProcess.optimization import OptimizationProblem
from CADETProcess.fractionation import FractionationOptimizer
from CADETProcess.performance import EluentConsumption
#Component definitions
component_system = ComponentSystem(2)
#Binding model
binding_model = Linear(component_system)
binding_model.adsorption_rate = [6, 8]
binding_model.desorption_rate = [1, 1]
#Column configuration
column = LumpedRateModelWithoutPores(component_system, name='master_column')
column.length = 0.6 # meters
column.diameter = 0.024 # meters
column.axial_dispersion = 4.4e-7 #m/s
column.total_porosity = 0.7 # v/v
column.binding_model = binding_model
# Inlet/Outlet configurations
#In's
feed = Inlet(component_system, name='feed')
feed.c = [10, 10] # M
feed.flow_rate = 2e-7 #m^3/s
eluent = Inlet(component_system, name='eluent')
eluent.c = [0, 0] # M
eluent.flow_rate = 6e-7 #m^3/s
#Outs
raffinate = Outlet(component_system, name='raffinate')
extract = Outlet(component_system, name='extract')
#Zones
zone_1 = SerialZone(component_system, 'zone_1', 1)
zone_2 = SerialZone(component_system, 'zone_2', 1)
zone_3 = SerialZone(component_system, 'zone_3', 1)
zone_4 = SerialZone(component_system, 'zone_4', 1)
#Carousel Build
builder = CarouselBuilder(component_system, 'smb')
builder.column = column
builder.add_unit(feed)
builder.add_unit(eluent)
builder.add_unit(raffinate)
builder.add_unit(extract)
builder.add_unit(zone_1)
builder.add_unit(zone_2)
builder.add_unit(zone_3)
builder.add_unit(zone_4)
# System Topology
builder.add_connection(eluent, zone_1)
builder.add_connection(zone_1, extract)
builder.add_connection(zone_1, zone_2)
w_e = .15
builder.set_output_state(zone_1, [w_e, 1-w_e])
builder.add_connection(zone_2, zone_3)
builder.add_connection(feed, zone_3)
builder.add_connection(zone_3, raffinate)
builder.add_connection(zone_3, zone_4)
w_r = 0.15
builder.set_output_state(zone_3, [w_r, 1-w_r])
builder.add_connection(zone_4, zone_1)
#Switch time and build
builder.switch_time = 300
process= builder.build_process()
# CSS Settings
process_simulator = Cadet()
evaluator = StationarityEvaluator()
criterion = RelativeArea()
criterion.threshold = 5e-3
evaluator.add_criterion(criterion)
process_simulator.stationarity_evaluator = evaluator
process_simulator.evaluate_stationarity = True
process_simulator.n_cycles_max = 5 #Just to speed things up
process_simulator.n_cycles_min = 1
#Optimization Definition
optimization_problem = OptimizationProblem('eluent_usage')
optimization_problem.add_evaluation_object(process)
optimization_problem.add_variable(
'switch_time.time',
lb=150, ub=600,
transform='auto'
)
optimization_problem.add_variable(
'builder.eluent.flow_rate',
lb=1e-7, ub=10e-7,
transform='auto'
)
optimization_problem.add_variable(
name='w_r',
lb=0, ub=1,
pre_processing=lambda x: [x[0], 1 - x[0]],
)
optimization_problem.add_variable(
name='w_e',
lb=0, ub=1,
)
# Setup Simulator
optimization_problem.add_evaluator(process_simulator)
# Setup Fractionator
frac_opt = FractionationOptimizer()
optimization_problem.add_evaluator(
frac_opt,
kwargs={'purity_required': [0.95, 0.95]}
)
# Setup Objectives
eluent_consumption = EluentConsumption()
optimization_problem.add_objective(
eluent_consumption,
n_objectives=2,
requires=[process_simulator, frac_opt],
minimize=False,
)
#Simulate Process
simulation_results = process_simulator.simulate(process)