[Guide] Particle size distributions in CADET-Process General Rate Model

Hi all,

I’m writing this on recommendation from some of the CADET devs (thanks @j.schmoelder and @ronald.jaepel!) for anyone who may be looking for a workaround to incorporate particle size distributions in their General Rate Model unit processes, which is not currently supported in CADET-Process but is in CADET-Core.

Please note that while I have tested this to some degree with my own models that this is not an official feature and is not covered by tests, unexpected issues could be encountered which may or may not have obvious effects.

Forking the repo

Since we need to make some changes to the CADET-Process source code we first need to make a fork of the CADET-Process repository on Github. For detailed instructions see the Github docs. I am assuming you are forking the master branch, however everything should work the same if you choose another (e.g. dev)

Making the changes to CADET-Process

After cloning your fork to your local machine you will need to make the following changes. The code shown in the blocks below are after the noted change, so you should be able to replace the lines in the specified file with the code from the block.

Modify CADETProcess/processModel/unitOperation.py

Add UnsignedList to the CADETProcess.dataStructure import statement.

from CADETProcess.dataStructure import (
    Constant, UnsignedFloat, UnsignedInteger,
    String, Switch,
    SizedUnsignedList,
    UnsignedList,                # Add
    Polynomial, NdPolynomial, SizedList, SizedNdArray
)

In the GeneralRateModel class, set particle_radius = UnsignedList() and and add par_type_volfrac = UnsignedList(ub=1).

class GeneralRateModel(TubularReactorBase):
    ...
    particle_radius = UnsignedList()             # Modify
    par_type_volfrac = UnsignedList(ub=1)        # Add
    ...
    # ub=1 allows values 0-1, this defines your particle volume fraction

Add par_type_volfrac to the GeneralRateModel._parameters list.

class GeneralRateModel(TubularReactorBase):
    ...
    _parameters = [
            'bed_porosity', 'particle_porosity', 'particle_radius',
            'par_type_volfrac',        # Add
            'film_diffusion', 'pore_accessibility',
            'pore_diffusion', 'surface_diffusion'
        ]
    ...

Modify CADETProcess/processModel/discretization.py

Add UnsignedList to the CADETProcess.dataStructure import statement.

from CADETProcess.dataStructure import (
    Constant, Bool, Switch,
    RangedInteger, UnsignedInteger, UnsignedFloat,
    SizedRangedList,
    UnsignedList        # Add

In the GRMDiscretizationFV class, set npar = UnsignedList().

class GRMDiscretizationFV(DiscretizationParametersBase):
    ...
    npar = UnsignedList()    # Modify
    ...

Still in GRMDiscretizationFV, update the par_disc_vector_length method return value.

    @property
    def par_disc_vector_length(self):
        """int: Number of entries in the particle discretization vector."""
        return sum([n + 1 for n in self.npar])    # Modify

Modify CADETProcess/simulator/cadetAdapter.py

Finally, in the ModelSolverParameters class unit_parameters_map dict, add 'PAR_TYPE_VOLFRAC': 'par_type_volfrac' in the GeneralRateModel.parameters sub-dict. The entire GeneralRateModel section of your dict should look the same as below.

    'GeneralRateModel': {
        'name': 'GENERAL_RATE_MODEL',
        'parameters': {
            'NCOMP': 'n_comp',
            'INIT_C': 'c',
            'INIT_Q': 'q',
            'INIT_CP': 'cp',
            'COL_DISPERSION': 'axial_dispersion',
            'COL_LENGTH': 'length',
            'COL_POROSITY': 'bed_porosity',
            'FILM_DIFFUSION': 'film_diffusion',
            'PAR_POROSITY': 'particle_porosity',
            'PAR_RADIUS': 'particle_radius',
            'PORE_ACCESSIBILITY': 'pore_accessibility',
            'PAR_DIFFUSION': 'pore_diffusion',
            'PAR_SURFDIFFUSION': 'surface_diffusion',
            'PAR_TYPE_VOLFRAC': 'par_type_volfrac',
            'CROSS_SECTION_AREA': 'cross_section_area',
            'VELOCITY': 'flow_direction',
        },
        'fixed': {
            'PAR_SURFDIFFUSION_MULTIPLEX': 0,
        },
    },

Installing your fork

Before installing your fork, I recommend creating a new virtual environment with your virtual environment manager of choice before installing your fork to preserve your mainline CADET-Process installation. You can easily clone a virtual environment in Conda with the following command.

conda create --name <new_env_name> --clone <env_to_clone>

If you are creating a virtual environment from scratch, be sure to install the other necessary packages like CADET-Core. Be sure to switch to your new environment once it is created if it is not activated automatically.

In your new environment you can now install your fork with pip using the following command. Optionally include the -e flag to install in editable mode if you need to make further changes.

pip install git+https://github.com/<your_username>/<your_fork_name>.git

# or include the "-e" flag to install in editable mode
pip install -e git+https://github.com/<your_username>/<your_fork_name>.git

Usage

You should now be able to use particle size distributions with the General Rate Model using the same syntax as CADET-Python, specified in the CADET-Core docs.

Hopefully this is helpful!
-Nick

5 Likes