Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ports / MCT Model (new PR) #95

Merged
merged 15 commits into from
Aug 14, 2024
Merged

Add ports / MCT Model (new PR) #95

merged 15 commits into from
Aug 14, 2024

Conversation

hannahlanzrath
Copy link
Collaborator

@hannahlanzrath hannahlanzrath commented Feb 13, 2024

(New PR after accidental merge)

This PR adds ports to UnitOperations in CADET process which are required by models such as the 2D-GRM.

For starters, we will test this with the Multi-Channel Transport-Model

To fix #3, we also need to fix #70.

To do

  • Add ports to add_connection method
  • Add discretization class for MCT
  • Add SolutionRecorder for MCT
  • Store connections with ports in FlowSheet
    • Add tests
    • How to expose discretization n_rad to flow_sheet/ports
  • Add check methods
    • Unconnected ports
    • Changes in discretization configuration
    • flow rate balance
  • Open question: Should ports have individual output states?
  • Add parameters to the Name Converter for the MCT in cadetAdapter
  • Create a SizedMatrix Type and/or check SizednDArray if it meets our requirements
  • Add MCT tests in test_unit_operation
    • add create_MCT
  • In unitOperation change flow_direction into array of Switches
  • move nchannel from discretization to model parameters
  • Check dimensionality for all unit operations, see also in solution
    • Create LWE for all Unit Operations
  • Overhaul solution method in simulationResults.py

For new PR?
Decision:

  • Add n_ports as a dimension for solutions
  • Make difference between Radial Coordinates and Channels

For Multiplexing PR?

  • Axial dipersion needs multiplexing to enable dependency on nchannel/state.
  • Flow direction needs multiplexing to enable dependency on nchannel.
  • Update/Add Tests for Multiplexing

Open question

Should the MCT (and other potential 2D models) inherit from TubularReactor? How would this look like.
Are dimensions retained in CADET-Process that are squashed in CADET-Core (see LRMP)? -> Line 740

Closed question

Should every channel of the MCT have a port by default? --> Yes

@daklauss
Copy link
Collaborator

    _connections = {
        'inlet': {
            'origins': {
                None: {                       
                }
            },
            'destinations': {
                None: {
                    'column': [None]                   
                }
            },
        }
    }
    connections = {
        'inlet': {
            'origins': {},
            'destinations': 
                {
                'column': None,
                'mct': ['channel_1'],
            },
        }
    }

@schmoelder schmoelder force-pushed the dev branch 6 times, most recently from f778466 to 0534130 Compare March 16, 2024 12:45
@schmoelder schmoelder force-pushed the dev branch 10 times, most recently from d10f69b to cd4c8ee Compare March 26, 2024 15:33
@hannahlanzrath
Copy link
Collaborator Author

In the current state, solution_bulk can handle solution outputs for the MCT with nchannel>1 (and I don't know why). The additional dimension n_ports still needs to be added to solution bulk. When setting up an MCT with nchannel = 1, solution.py drops an error (which I would expect as well in the nchannel>1 case) stemming from the wrong dimensionality. Thus n_ports needs to be added as a dimension in one of the solution classes.
We could think of making a SolutionClass specifically for Units with ports to handle this?

@hannahlanzrath
Copy link
Collaborator Author

In addition to my comment above:

test_mct_simulation.zip

Not-working example with 1 channel:

from CADETProcess.processModel import Inlet, Outlet, MCT
from CADETProcess.processModel import FlowSheet
from CADETProcess.processModel import Process

from CADETProcess.simulator import Cadet

import numpy as np

component_system = ComponentSystem(1)

mct_flow_sheet = FlowSheet(component_system)

inlet = Inlet(component_system, name='inlet')
mct = MCT(component_system,nchannel=1, name='mct')
outlet = Outlet(component_system, name='outlet1')

mct.solution_recorder.write_solution_bulk = 1

mct_flow_sheet.add_unit(inlet)
mct_flow_sheet.add_unit(mct)
mct_flow_sheet.add_unit(outlet)

mct_flow_sheet.add_connection(inlet, mct, destination_port='channel_0')
mct_flow_sheet.add_connection(mct, outlet, origin_port='channel_0')

process = Process(mct_flow_sheet, 'Tracer_Transport')

inlet.flow_rate = 8e-5

mct.length = 0.3
mct.channel_cross_section_areas = [1,]
mct.axial_dispersion = 0
mct.exchange_matrix = np.array([[0.0]])

process.cycle_time = 120*60

_ = process.add_event('Start', 'flow_sheet.inlet.c', [1], 0)
_ = process.add_event('Stop', 'flow_sheet.inlet.c', [0], 1*60)

process_simulator = Cadet(install_path='') #Add your CADET path pointing to a CADET version with MCT here
process_simulator.check_cadet()
simulation_results = process_simulator.simulate(process)

Working example with multiple channels

from CADETProcess.processModel import ComponentSystem
from CADETProcess.processModel import Inlet, Outlet, MCT
from CADETProcess.processModel import FlowSheet
from CADETProcess.processModel import Process

from CADETProcess.simulator import Cadet

import numpy as np

component_system = ComponentSystem(1)

mct_flow_sheet = FlowSheet(component_system)

inlet = Inlet(component_system, name='inlet')
mct_3c = MCT(component_system,nchannel=3, name='mct_3c')
mct_2c1 = MCT(component_system,nchannel=2, name='mct_2c1')
mct_2c2 = MCT(component_system,nchannel=2, name='mct_2c2')
outlet1 = Outlet(component_system, name='outlet1')
outlet2 = Outlet(component_system, name='outlet2')

mct_3c.solution_recorder.write_solution_bulk = 1
mct_2c1.solution_recorder.write_solution_bulk = 1
mct_2c2.solution_recorder.write_solution_bulk = 1

mct_flow_sheet.add_unit(inlet)
mct_flow_sheet.add_unit(mct_3c)
mct_flow_sheet.add_unit(mct_2c1)
mct_flow_sheet.add_unit(mct_2c2)
mct_flow_sheet.add_unit(outlet1)
mct_flow_sheet.add_unit(outlet2)

mct_flow_sheet.add_connection(inlet, mct_3c, destination_port='channel_0')
mct_flow_sheet.add_connection(mct_3c, mct_2c1, origin_port='channel_0', destination_port='channel_0')
mct_flow_sheet.add_connection(mct_3c, mct_2c1, origin_port='channel_0', destination_port='channel_1')
mct_flow_sheet.add_connection(mct_3c, mct_2c2, origin_port='channel_1', destination_port='channel_0')
mct_flow_sheet.add_connection(mct_2c1, outlet1, origin_port='channel_0')
mct_flow_sheet.add_connection(mct_2c1, outlet1, origin_port='channel_1')
mct_flow_sheet.add_connection(mct_2c2, outlet2, origin_port='channel_1')

process = Process(mct_flow_sheet, 'Tracer_Transport')

inlet.flow_rate = 8e-5

mct_3c.length = 0.3
mct_3c.channel_cross_section_areas = [1,1,1]
mct_3c.axial_dispersion = 0
mct_3c.exchange_matrix = np.array([[
    [0.0,0.01,0.0],
    [0.02,0.0,0.03],
    [0.0,0.0,0.0]
]])

mct_2c1.length = 0.3
mct_2c1.channel_cross_section_areas = [1,1]
mct_2c1.axial_dispersion = 0
mct_2c1.exchange_matrix = np.array([[
    [0.0,0.0],
    [0.0,0.0],

]])

mct_2c2.length = 0.3
mct_2c2.channel_cross_section_areas = [1,1]
mct_2c2.axial_dispersion = 0
mct_2c2.exchange_matrix = np.array([[
    [0.0,0.0],
    [0.0,0.0],

]])

process.cycle_time = 120*60

_ = process.add_event('Start', 'flow_sheet.inlet.c', [1], 0)
_ = process.add_event('Stop', 'flow_sheet.inlet.c', [0], 1*60)

process_simulator = Cadet(install_path='C:/cadet_from_source/cadet/')
process_simulator.check_cadet()
simulation_results = process_simulator.simulate(process)

@hannahlanzrath
Copy link
Collaborator Author

hannahlanzrath commented Apr 22, 2024

MRE (Can someone maybe confirm the problem on the add_ports branch to make sure it is not a problem with my GIT or local files?)

from CADETProcess.processModel import Inlet, Outlet, Cstr
from CADETProcess.processModel import ComponentSystem
from CADETProcess.processModel import FlowSheet
from CADETProcess.processModel import Process
from CADETProcess.simulator import Cadet

import numpy as np

component_system = ComponentSystem(1)
flow_sheet = FlowSheet(component_system)
inlet = Inlet(component_system, 'inlet')
cstr = Cstr(component_system, 'cstr')

flow_sheet.add_unit(inlet)
flow_sheet.add_unit(cstr)


flow_sheet.add_connection(inlet, cstr)

process = Process(flow_sheet, 'Tracer_Transport')
cstr.V = 1e-8
process.cycle_time = 200*60
inlet.flow_rate = 1e-9

_ = process.add_event('Base', 'flow_sheet.inlet.c', [0], 0)
_ = process.add_event('Start', 'flow_sheet.inlet.c', [1], 50*60)
_ = process.add_event('Stop', 'flow_sheet.inlet.c', [0], 150*60)

process_simulator = Cadet()
process_simulator.check_cadet()
simulation_results = process_simulator.simulate(process)

simulation_results.solution.cstr.outlet.plot()

Output for the add_ports branch:
image

Expected Output (e.g. master branch):

image

@schmoelder
Copy link
Contributor

Can confirm...

I would have a look at the CADETAdapter. Maybe you're inadvertently reading the same solution for inlets and outlets?

@schmoelder
Copy link
Contributor

Hey @hannahlanzrath @daklauss Could you please update this PR and let me know what's missing s.t. we can merge?

@hannahlanzrath
Copy link
Collaborator Author

I merged create_LWE into add_ports and rebased. From my side we're good to merge this first version of add_ports support into dev :) Please also have a look at the commits and if they should be even more clustered or not. Thank you <3

@hannahlanzrath
Copy link
Collaborator Author

I noticed that ports were not added for parameter sensitivities and added the compatibility. In #166 I want to add tests including sensitivities to ensure we cover that.

How is our current stand on merging this branch into dev?

@hannahlanzrath hannahlanzrath force-pushed the add_ports branch 5 times, most recently from 5e07da6 to f704499 Compare August 6, 2024 12:29
hannahlanzrath and others added 15 commits August 14, 2024 12:43
Co-authored-by: Johannes Schmölder <[email protected]>
Co-authored-by: daklauss <[email protected]>
Co-authored-by: Johannes Schmölder <[email protected]>
Co-authored-by: daklauss <[email protected]>
Co-authored-by: Lanzrath, Hannah <[email protected]>
Co-authored-by: Johannes Schmölder <[email protected]>
Co-authored-by: daklauss <[email protected]>
Co-authored-by: daklauss <[email protected]>
Co-authored-by: Johannes Schmölder <[email protected]>
Co-authored-by: daklauss <[email protected]>
Co-authored-by: Johannes Schmölder <[email protected]>
Co-authored-by: Johannes Schmölder <[email protected]>
Co-authored-by: Lanzrath, Hannah <[email protected]>
Co-authored-by: daklauss <[email protected]>
Co-authored-by: Johannes Schmölder <[email protected]>
Co-authored-by: Johannes Schmölder <[email protected]>
Co-authored-by: daklauss <[email protected]>
Co-authored-by: Lanzrath, Hannah <[email protected]>
Co-authored-by: Johannes Schmölder <[email protected]>
Co-authored-by: Lanzrath, Hannah <[email protected]>
Co-authored-by: Lanzrath, Hannah <[email protected]>
Co-authored-by: Johannes Schmölder <[email protected]>
Use relative imports in tests, to make it compatible with pytest.
Adds create_LWE, a collection of functions to quickly and semi-modularly
set up a load-wash-elude process with CADET-Process

Co-authored-by: Johannes Schmölder <[email protected]>
Adds tests for the LWE process and simulation results

Co-authored-by: Johannes Schmölder <[email protected]>
@schmoelder schmoelder merged commit 0794a23 into dev Aug 14, 2024
5 checks passed
@schmoelder schmoelder deleted the add_ports branch August 14, 2024 11:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants