Brief update:
I have found the cause. It works with the following line of code:
optimization_problem.add_linear_equality_constraint(['axial_dispersion_tubing', 'axial_dispersion_tubing2'], lhs=[1, -1], beq=0, eps=1e-9)
However, I now get an error during optimization:
CADETProcessError Traceback (most recent call last)
Cell In[14], line 2
1 if __name__ == '__main__':
----> 2 optimization_results = optimizer.optimize(
3 optimization_problem, x0,
4 use_checkpoint=True
5 )
File ~\anaconda3\envs\MasterNew\lib\site-packages\CADETProcess\optimization\optimizer.py:260, in OptimizerBase.optimize(self, optimization_problem, x0, save_results, results_directory, use_checkpoint, overwrite_results_directory, exist_ok, log_level, reinit_cache, delete_cache, *args, **kwargs)
256 plt.switch_backend('agg')
258 start = time.time()
--> 260 self.run(self.optimization_problem, x0, *args, **kwargs)
262 self.results.time_elapsed = time.time() - start
264 if delete_cache:
File ~\anaconda3\envs\MasterNew\lib\site-packages\CADETProcess\optimization\pymooAdapter.py:92, in PymooInterface.run(self, optimization_problem, x0)
90 if len(pop) < pop_size:
91 n_remaining = pop_size - len(pop)
---> 92 remaining = optimization_problem.create_initial_values(
93 n_remaining, method='chebyshev', seed=self.seed,
94 burn_in=burn_in
95 )
96 pop = np.vstack((pop, remaining))
97 elif len(pop) > pop_size:
File ~\anaconda3\envs\MasterNew\lib\site-packages\CADETProcess\optimization\optimizationProblem.py:2780, in OptimizationProblem.create_initial_values(self, n_samples, method, seed, burn_in)
2778 while len(values) < n_samples:
2779 if counter > burn_in:
-> 2780 raise CADETProcessError(
2781 "Cannot find invididuals that fulfill constraints."
2782 )
2784 counter += 1
2785 i = rng.integers(0, burn_in)
CADETProcessError: Cannot find invididuals that fulfill constraints.
I think it’s best if I share the whole code with the following experimental data:
NaCl_Normalized.csv (63.0 KB)
from CADETProcess.processModel import ComponentSystem
from CADETProcess.processModel import StericMassAction
from CADETProcess.processModel import Inlet, GeneralRateModel, Outlet,TubularReactor, Cstr,LumpedRateModelWithPores
from CADETProcess.processModel import FlowSheet
from CADETProcess.processModel import Process
from CADETProcess.simulator import Cadet
import numpy as np
Q_ml_min = 0.5 # ml/min
Q_m3_s = Q_ml_min/(60*1e6) #m3/s
V_tracer = 5e-8
component_system = ComponentSystem()
component_system.add_component('Salt')
# Unit Operations
inlet = Inlet(component_system, name='inlet')
inlet.flow_rate = Q_m3_s
column = LumpedRateModelWithPores(component_system, 'column')
column.length = 0.1
column.diameter = 0.0077
column.bed_porosity = 0.19
column.particle_radius = 3.4e-5
column.particle_porosity = 0.8333
column.axial_dispersion =4.41924993e-08
column.film_diffusion = [1.829e-4]
# Tubing1
tubing1 = TubularReactor(component_system, 'tubing1')
tubing1.length = 0.534
tubing1.cross_section_area = 4.418e-7
tubing1.axial_dispersion = 8.97920728e-04
tubing2 = TubularReactor(component_system, 'tubing2')
tubing2.length = 0.534
tubing2.cross_section_area = 4.418e-7
tubing2.axial_dispersion = 8.97920728e-04
uv_detector = Cstr(component_system, name='uv_detector')
uv_detector.V = 2e-9
uv_detector.c = [0]
outlet = Outlet(component_system, name='outlet')
# Flow Sheet
flow_sheet = FlowSheet(component_system)
flow_sheet.add_unit(inlet)
flow_sheet.add_unit(column)
flow_sheet.add_unit(outlet)
flow_sheet.add_unit(tubing1)
flow_sheet.add_unit(tubing2)
flow_sheet.add_unit(uv_detector)
flow_sheet.add_connection(inlet, tubing1)
flow_sheet.add_connection(tubing1, column)
flow_sheet.add_connection(column, tubing2)
flow_sheet.add_connection(tubing2, uv_detector)
flow_sheet.add_connection(uv_detector, outlet)
# Process
process = Process(flow_sheet, 'lwe')
process.cycle_time = 1200
_ = process.add_event('Pre-Wash', 'flow_sheet.inlet.c', [0],0)
_ = process.add_event('Injection', 'flow_sheet.inlet.c', [500], 60)
_ = process.add_event('Wash', 'flow_sheet.inlet.c', [0],(V_tracer/Q_m3_s+60))
process_simulator = Cadet()
simulation_results = process_simulator.simulate(process)
fig, ax = simulation_results.solution.outlet.outlet.plot()
from CADETProcess.reference import ReferenceIO
import numpy as np
data_uv_2 = np.loadtxt('NaCl_Normalized.csv', delimiter=',')
time_uv_2 = data_uv_2[:, 0] * 60
uv_2 = data_uv_2[:, 1]
reference = ReferenceIO('NaCl experiment', time_uv_2, uv_2)
_ = reference.plot()
from CADETProcess.comparison import Comparator
comparator = Comparator()
comparator.add_reference(reference)
comparator.add_difference_metric(
'PeakPosition', reference,
'outlet.outlet'
)
comparator.add_difference_metric(
'PeakHeight', reference,
'outlet.outlet'
)
from CADETProcess.simulator import Cadet
simulator = Cadet()
simulation_results = simulator.simulate(process)
metrics = comparator.evaluate(simulation_results)
print(metrics)
plot= comparator.plot_comparison(simulation_results)
from CADETProcess.optimization import OptimizationProblem
optimization_problem = OptimizationProblem('AxialDispersion_PositionHeight')
optimization_problem.add_evaluation_object(process)
optimization_problem.add_variable(
name='axial_dispersion_column', parameter_path='flow_sheet.column.axial_dispersion',
lb=1e-10, ub=0.1,
transform='auto'
)
optimization_problem.add_variable(
name='axial_dispersion_tubing', parameter_path='flow_sheet.tubing1.axial_dispersion',
lb=1e-9, ub=0.1,
transform='auto'
)
optimization_problem.add_variable(
name='axial_dispersion_tubing2', parameter_path='flow_sheet.tubing2.axial_dispersion',
lb=1e-9, ub=0.1,
transform='auto'
)
optimization_problem.add_linear_equality_constraint(['axial_dispersion_tubing', 'axial_dispersion_tubing2'], lhs=[1, -1], beq=0, eps=1e-9)
#optimization_problem.add_linear_equality_constraint(['axial_dispersion_tubing', 'axial_dispersion_tubing2'], lhs=[1e5, -1e5], beq=0, eps=1e-4) # I have also tried this
optimization_problem.add_evaluator(simulator)
optimization_problem.add_objective(
comparator,
n_objectives=comparator.n_metrics,
requires=[simulator]
)
def callback(simulation_results, individual, evaluation_object, callbacks_dir='./'):
comparator.plot_comparison(
simulation_results,
file_name=f'{callbacks_dir}/{individual.id}_{evaluation_object}_comparison.png',
show=False
)
optimization_problem.add_callback(callback, requires=[simulator])
x0=[[5e-08, 5e-06,5e-06]]
#x0=optimization_problem.create_initial_values(method='chebyshev')
from CADETProcess.optimization import U_NSGA3
optimizer = U_NSGA3()
optimizer.n_cores = 4
optimizer.pop_size = 50
optimizer.n_max_gen = 5
if __name__ == '__main__':
optimization_results = optimizer.optimize(
optimization_problem, x0,
use_checkpoint=False
)
Epsilon must be chosen very low, as the axial dispersion is very small. As shown above, I have also tried multiplication with a pre-factor and other possibilities (e.g. with initial values generated by the appropriate method).
Can anyone help me?