GIEX setup in CADET-Process

Hi Cadet-Devs,

I’m trying to setup the GIEX isotherm in CADET-Process to evaluate the influence of interaction-modyfing components.

Unfortunately the setup fails immediately due to the size of the characteristic_charge parameter which is for some reason expected to be 0 for check_size.

Furthermore, I don’t understand what the characteristic_charge_breaks parameter as this parameter is not found in the CADET core documentation. Could you please explain. Btw. there is also a mistake in the CADET-Process documentation regarding this parameter.

MinExample on current dev branch:

import CADETProcess

from CADETProcess.processModel import ComponentSystem
component_system = ComponentSystem(['Salt', 'Mod', 'P1', 'P2'])

from CADETProcess.processModel import GeneralizedIonExchange
binding_model = GeneralizedIonExchange(component_system, name = 'GIEX')
binding_model.is_kinetic = 1
binding_model.adsorption_rate = [0, 0, 1, 1]
binding_model.desorption_rate = [0, 0, 1, 1] 

binding_model.adsorption_rate_linear = [0,0,0,0] 
binding_model.characteristic_charge_breaks  = [0,0,0,0] # ?
binding_model.characteristic_charge = [0, 0, 1, 1]

binding_model.steric_factor = [0,0,0,0]
binding_model.capacity  = 1

Error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[12], line 15
     13 binding_model.adsorption_rate_linear = [0,0,0,0] 
     14 binding_model.characteristic_charge_breaks  = [0,0,0,0] # ?
---> 15 binding_model.characteristic_charge = [0, 0, 1, 1]
     17 binding_model.steric_factor = [0,0,0,0] # steric factor
     18 binding_model.capacity  = 1 #mol/m^3 solid phase

File c:\ProgramData\Anaconda3\envs\cadet_dev\lib\site-packages\CADETProcess\dataStructure\dataStructure.py:477, in frozen_attributes.<locals>.frozensetattr(self, key, value)
    473     raise AttributeError(
    474         f"{cls.__name__} object has no attribute {key}"
    475     )
    476 else:
--> 477     object.__setattr__(self, key, value)

File c:\ProgramData\Anaconda3\envs\cadet_dev\lib\site-packages\CADETProcess\dataStructure\parameter.py:171, in ParameterBase.__set__(self, instance, value)
    169 if value is not None:
    170     value = self._prepare(instance, value, recursive=True)
--> 171     self._check(instance, value, recursive=True)
    173 try:
    174     if self.name in instance._parameters:

File c:\ProgramData\Anaconda3\envs\cadet_dev\lib\site-packages\CADETProcess\dataStructure\parameter.py:483, in Typed._check(self, instance, value, recursive)
    480     raise TypeError(f"Expected type {self.ty}, got {type(value)}")
    482 if recursive:
--> 483     super()._check(instance, value, recursive)

File c:\ProgramData\Anaconda3\envs\cadet_dev\lib\site-packages\CADETProcess\dataStructure\parameter.py:1105, in Sized._check(self, instance, value, recursive)
   1092 def _check(self, instance, value, recursive=False):
   1093     """
   1094     Validate the provided value's size.
   1095 
   (...)
   1103         If True, perform the check recursively. Defaults to False.
   1104     """
-> 1105     self.check_size(instance, value)
   1107     if recursive:
   1108         super()._check(instance, value, recursive)

File c:\ProgramData\Anaconda3\envs\cadet_dev\lib\site-packages\CADETProcess\dataStructure\parameter.py:1042, in Sized.check_size(self, instance, value)
   1039 exptected_size = self.get_expected_size(instance)
   1041 if size != exptected_size:
-> 1042     raise ValueError(f"Expected size {exptected_size}")

ValueError: Expected size 0

I did some more research and I think I got it now. CADET-Process is currently a bit more advanced than CADET core when it comes to the GIEX model, right? The piecewise polynomial charge modulator did not make it to the stable CADET branch yet, but it is already implemented in the CADET-Process, at least in the dev branch I’m using.

I solved my issue by commenting out the relevant code lines in binding.py and cadetAdapter.py refering to characteristic_charge_breaks and set n_pieces = 1. Now it works for me. Nevertheless, the error above will appear once you want to use the piecewise polynomial charge modulator.

Hey,

That’s correct. With the separation of CADET-Core and CADET-Process, it can sometimes be a challenge to keep things in sync when new features are added. In future, we will need some better system. Also, our initial idea for extending the GIEX never fully gained traction and eventually lost its momentum.

Ok, I believe the issue is that it was previously not well documented.
First, you need to define (for each component) the break points, i.e. the section boundaries of the piecewise cubic polynomial. Note that the length must be a multiple of n_comp and the data is component-major:

Note that entries of non-binding components must be provided but will be ignored.


breaks_Salt = [0, 1, 2]
breaks_Mod = [0, 1, 2]
breaks_P1 = [0, 1, 2]
breaks_P2 = [0, 1, 2]

binding_model.characteristic_charge_breaks  = breaks_Salt + breaks_Mod + breaks_P1 + breaks_P2

Then, for each “section”, you need to provide the corresponding entries for characteristic_charge.

binding_model.characteristic_charge = [
    0, 0, # salt section 0, salt section 1
    0, 0, # mod section 0, mod section 1
    1, 2, # P1, section 0, P1, section 1
    1, 2, # P2, section 0, P2, section 1
]
[...]

characteristic_charge_linear and the others are optional.

Since this is a bit error prone, because there could be issues with discontinuities, we have also considered providing an interface where simply nodes can be provided but this is currently not implemented.

Hope that helps.

I’ve updated the documentation (and fixed a small bug with modulated parameters such as the characteristic_charge_breaks) in a PR that you can find here.

1 Like

Ah, and needless to say, all of this only works if you use this dev Version of CADET-Core. However, if you ignore the breaks, it should (in theory) be downward compatible. Let me know if there are other issues.

@ortler: characteristic_charge_breaks is now optional. All it needed was an is_optional=True :sweat_smile:: https://github.com/fau-advanced-separations/CADET-Process/blob/676dd71d0273848511dcbbe63f65e6c4df3de3d5/CADETProcess/processModel/binding.py#L979

2 Likes

I’m curious to hear more about these ideas on extending the GIEX. I know that \nu (characteristic charge) can have a polynomial form dependence on pH, namely

\nu = \nu_2\left(\mathrm{pH}\right)^2 + \nu_1\left(\mathrm{pH}\right) + \nu_0

This is available in CADET-Core, so I assume that the piecewise polynomial charge modulator (my first time hearing about this) is something else. Would love some clarification :slight_smile:

In the GGIEX (the Generalized Generalized Ion Exchange Model), the pH dependence of \nu can be described as a piecewise cubic polynomial. Otherwise, it’s the same model.

1 Like