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 Multi Channel Transport Model (MCT) #95

Merged
merged 3 commits into from
Jun 19, 2024
Merged

Add Multi Channel Transport Model (MCT) #95

merged 3 commits into from
Jun 19, 2024

Conversation

schmoelder
Copy link
Contributor

@schmoelder schmoelder commented Jul 5, 2021

This PR implements a modified 2D-GRM to model plant root systems as described here

To-do

@schmoelder schmoelder force-pushed the feature/tractor branch 2 times, most recently from 8fe0d02 to 7a5de59 Compare July 5, 2021 16:11
@sleweke-bayer
Copy link
Contributor

Where does the name Tractor come from? Maybe a more neutral name that can be understood by non-insiders would be fitting?
Suggestion: CompartmentTransportModel

@Immudzen
Copy link
Contributor

Immudzen commented Jul 6, 2021

I agree with giving it a descriptive name. That also makes it easier to use the name or if it appears in a presentation, paper etc.

@schmoelder
Copy link
Contributor Author

Oh yes, it's just a working title because @hannahlanzrath is still checking with her supervisor what to call it.

Copy link
Contributor Author

@schmoelder schmoelder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need separate function for it or can we just read the parameter like any other model parameter?

@jazib-hassan-juelich
Copy link
Contributor

I don't think we will have the decay terms here. It's easier to use the existing reactions interface.

agreed, but I just added the general framework and as soon as I have information from Hannah about the actual interface then I will made modifications accordingly.

@jazib-hassan-juelich
Copy link
Contributor

Do we need separate function for it or can we just read the parameter like any other model parameter?

In my view, adding a specific configuration function to read the parameters of this particular model makes the tracibility of the current implementation a bit straight forward. Just my opinion. Else we can read them like the other parameters.

Copy link
Contributor

@sleweke-bayer sleweke-bayer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That will work as a first shot but is going to be inefficient.
I'd prefer setting the sparsity pattern based on the actual exchange matrix structure (i.e., only add non-zeros in the pattern for compartments that actually communicate).
To this end, setSparsityPattern() can be called in configure() instead of configureModelDiscretization().

@schmoelder schmoelder force-pushed the feature/tractor branch 2 times, most recently from f0d3248 to af94b64 Compare July 20, 2021 07:58
@schmoelder
Copy link
Contributor Author

schmoelder commented Jul 20, 2021

I'd prefer setting the sparsity pattern based on the actual exchange matrix structure (i.e., only add non-zeros in the pattern for compartments that actually communicate).

We fixed that by only adding the pattern only if the entry in the matrix is non-zero.

To this end, setSparsityPattern() can be called in configure() instead of configureModelDiscretization().

@jazib-hassan-juelich @jayghoshter yesterday, you had a look at the order of calling the various configure functions. Any comments on that?

Other than that, we're still awaiting tests from @hannahlanzrath but I hope it works now.

We also implemented the exchange matrix s.t. it also would work for multiple components.

assuming e_{i,j,k} describes the transport of component k from compartment i to j, the matrix has the following form (assuming a 2 component system):
[
0, 0, e_{0,1,0}, e_{0,1,1}, e_{0,2,0}, e_{0,2,1}, ...
e_{1,0,0}, e_{1,0,1}, 0, 0, e_{1,2,0}, e_{1,2,1}, ...
...
]

@Immudzen also suggested we could take a similar approach to how we setup the connections, meaning that we only specify [compartment_from, compartment_to, component_index, exchange_rate].
This would simplify the user interface but I suggest we leave that for the python side to figure out.

@schmoelder schmoelder force-pushed the feature/tractor branch 2 times, most recently from 8dc4028 to 74059fd Compare July 21, 2021 09:16
@schmoelder
Copy link
Contributor Author

To this end, setSparsityPattern() can be called in configure() instead of configureModelDiscretization().

@jazib-hassan-juelich @jayghoshter yesterday, you had a look at the order of calling the various configure functions. Any comments on that?

ping @jayghoshter @jazib-hassan-juelich

@jazib-hassan-juelich
Copy link
Contributor

jazib-hassan-juelich commented Jul 29, 2021

To this end, setSparsityPattern() can be called in configure() instead of configureModelDiscretization().

@jazib-hassan-juelich @jayghoshter yesterday, you had a look at the order of calling the various configure functions. Any comments on that?

If I remember correctly, we first tried to implement the exchange matrix in the configure function, but then we faced the problem in the residualImpl Function in Line that the exchange matrix had no entries which caused the simulation to fail. Due to this issue we defined the exchange matrix configureModelDiscretization() so that when this function is called exhange matrix is already defined.
Alongwith @Immudzen and @jayghoshter I looked deep into this issue and it relates to the order of calling these functions and when we try to change the order then broke the code. @jayghoshter can add more to this.

@jayghoshter
Copy link
Member

Not much more to comment. As @jazib-hassan-juelich wrote, configureModelDiscretization() is called before configure() in ModelBuilderImpl.cpp:183.

if (!model->configureModelDiscretization(paramProvider, *this) || !model->configure(paramProvider))

I think the issue was that setSparsityPattern() is called in configureModelDiscretization and needs _exchangeMatrix to be defined.


for (unsigned int comp = 0; comp < _nComp; ++comp)
{
const ParamType exchange_orig_dest_comp = static_cast<ParamType>(_exchangeMatrix[rad_orig * _nRad * _nComp + rad_dest * _nComp + comp]);
Copy link
Contributor

@sleweke sleweke Aug 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will always be active. In fact, it doesn't really matter. So no need for this function to be a template. Just choose between double and active.

@sleweke
Copy link
Contributor

sleweke commented Aug 8, 2021

I think the issue was that setSparsityPattern() is called in configureModelDiscretization and needs _exchangeMatrix to be defined.

Well, then don't call it at this point 😛 It makes more sense to read the exchange matrix in configure(). Instead of calling setSparsityPattern() in configureModelDiscretization(), just call it in configure() when everything is known.

Comment on lines 1153 to 1156
_jacC.centered(offsetCur_orig, 0) += static_cast<double>(exchange_orig_dest_comp);
_jacC.centered(offsetCur_orig, offsetCur_dest) -= static_cast<double>(exchange_orig_dest_comp);
_jacC.centered(offsetCur_dest, 0) -= static_cast<double>(exchange_orig_dest_comp);
_jacC.centered(offsetCur_dest, offsetCur_orig) += static_cast<double>(exchange_orig_dest_comp);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have changes in two different residuals (is this correct? Could already be accounted for in _exchangeMatrix). In each change, only one state vector item is involved. Hence, we should see two changes in the Jacobian:

  • d resCur_orig / d yCur_orig = exchange_orig_dest_comp
  • d resCur_dest / d yCur_orig = -exchange_orig_dest_comp

We also need to take into account that the second argument of centered() refers to the offset on the main diagonal of the matrix. That is, centered(x,y) refers to matrix item mat_{x, x+y}.

This leads to the code

_jacC.centered(offsetCur_orig, 0) += static_cast<double>(exchange_orig_dest_comp);
_jacC.centered(offsetCur_dest, static_cast<int>(offsetCur_orig) - static_cast<int>(offsetCur_dest)) -= static_cast<double>(exchange_orig_dest_comp);

Since resCur_orig corresponds to yCur_orig, we get diagonal 0. For the second, we need the offset from resCur_dest to yCur_orig. From our current position (diagonal 0, equivalent to resCur_dest), we go back to the origin (-offsetCur_dest) and from there to yCur_orig (+offsetCur_orig). Note that we need to convert to int because unsigned int does not allow for negative offsets.

@sleweke
Copy link
Contributor

sleweke commented Aug 8, 2021

General remarks:

  • Please use consistent indentation (tabs?).
  • What about some unit tests (e.g., analytic Jacobain vs. finite differences)?

@schmoelder
Copy link
Contributor Author

sorry, I made a mess while trying to rebase. I will clean up and force push.

@sleweke-bayer
Copy link
Contributor

@hannahlanzrath has put some test cases on sciebo(?). If those work correctly, we can rebase and merge.
However, adding some unit tests before merging would be great.

@schmoelder schmoelder changed the title Include compartment model for Tractor Add Multi Channel Transport Model (MCT) Sep 20, 2021
@schmoelder
Copy link
Contributor Author

We need to make sure to also implement the fix for dynamic flow rates provided in #101.

@schmoelder
Copy link
Contributor Author

Hi Hannah,

sorry for the long silence.

If we look at the to-dos, we're only missing a unit test. Maybe we can get this done next Friday during our Core-Dev Meeting. Other than that, we're good to go.

@hannahlanzrath
Copy link
Collaborator

MCT_demo.zip

@hannahlanzrath
Copy link
Collaborator

hannahlanzrath commented Aug 18, 2023

Update on the Unittest Issue

A Unittest file (test->MultiChannelTransportModel.cpp) was added, and a simple test case created, that compares the outlets of two seperate channels with the same configuration.

  • From there on, more test cases can be added (I think I could do that, maybe with a little help of someone knows the language better)
  • The test cases from the Jacobian must be modified so they use the MCT file (? I am not sure how that would be solved)

Also we rebased as a preparation to merge into the main branch

@hannahlanzrath
Copy link
Collaborator

What would be the right way to pull now to avoid merge conflicts and just get the current version?

@schmoelder
Copy link
Contributor Author

If you don't have any local changes, try the following:

git fetch                                              # This updates the local git repo with information about the upstream branches
git reset --hard origin/tractor        # This will set the local branch to exactly the state of the remote branch.

@hannahlanzrath
Copy link
Collaborator

hannahlanzrath commented Nov 7, 2023

Today Jan and I worked on the Unittests:

  • We added a Unittest that Compares the Output of two simulations Running Exchange from Channel 1 to Channel 2 and vice versa
  • In JasonTestModels.cpp we added the case MULTI_CHANNEL_TRANSPORT with NCHANNEL and CHANNEL_CROSS_SECTION_AREAS for the Jacobian Tests and added them in test->MultiChannelTransportModel.cpp (some of those FAIL)
  • We added the MCT as well for the LWE specifying NCHANNEL=1 to get the other tests working
  • In test->MultiChannelTransportModel.cpp we added a Unittest for backwards flow based on the one for the other models, butit fails -> We tested forwards and backward flow and looked at the output graphically, for the backward flow it shows artifacts in the beginning even with high ncol and abs/rel tolerances for the solver. Ideas?

TODO for DevCall Nov:

  • Find out why the backwards flow Test does not work
  • Find out why some of the Jacobian Tests do not work (Note: For the other models there were also some tests not working)
  • If these are issues with cadet core and not the tests itself: Publish MCT

@hannahlanzrath
Copy link
Collaborator

Jan and I found out that the Jacobian tests fail for the GRM2D as well. The fowards/backwards tests do not work for any of the models, we even tested on a branch without MCT. Thus the tests not working likely has nothing to do with the implementation of the MCT but a general problem of the cadet-core. We will check the commits if we find a state in which these tests were still working.

@hannahlanzrath
Copy link
Collaborator

Sam added, that for the 2DGRM Algorithmic Differentiation is not working, so

  • Comment out AD tests for MCT and 2DGRM

@hannahlanzrath
Copy link
Collaborator

hannahlanzrath commented Dec 6, 2023

Johannes and I noticed, that the Exchange Matrix is not only nchannel x nchannel but can be defined for every component, so

  • Exchange Matrix Documentation in Interface should say size nchannel x nchannel x ncomp

@jbreue16
Copy link
Contributor

jbreue16 commented Feb 7, 2024

Ive fixed the MCT backwards flow and updated the tests:
We now have tests for simple logics: fwd vs bwd flow; fwd vs bwd exchange; two channels with same inlet yield same result.

We should add a test against a reference solution. @hannahlanzrath I think its alright to use the LRM without porosity to generate one. Maybe @sleweke can generate an analytical one using CADET-semianalytic sometime.

@ronald-jaepel
Copy link
Collaborator

ronald-jaepel commented Mar 12, 2024

Heads up:

Before merging, this branch would have to be rebased anyways, so we went ahead an rebased it now to get it to play nicely with the update build instructions. This will, however, break workflows for people using this branch with the old build instructions (I think). Therefore I haven't force pushed the rebased branch onto this branch but create a new one. Let's discuss in which order to merge these changes Wednesday in the office.

@hannahlanzrath hannahlanzrath marked this pull request as ready for review June 18, 2024 13:47
sleweke and others added 3 commits June 19, 2024 14:34
* Original implementation (Samuel Leweke)

* Bug fixes (Jan Breuer, Johannes Schmoelder, Hannah Lanzrath)

Co-authored-by: Jan Breuer <jan.breuer@fz-juelich.de>
Co-authored-by: Johannes Schmoelder <j.schmoelder@fz-juelich.de>
Co-authored-by: Hannah Lanzrath <h.lanzrath@fz-juelich.de>
Co-authored-by: Hannah Lanzrath <h.lanzrath@fz-juelich.de>
@jbreue16 jbreue16 merged commit 7aadb13 into master Jun 19, 2024
3 checks passed
jbreue16 added a commit that referenced this pull request Jun 19, 2024
* Original implementation (Samuel Leweke)

* Bug fixes (Jan Breuer, Johannes Schmoelder, Hannah Lanzrath)

Co-authored-by: Jan Breuer <jan.breuer@fz-juelich.de>
Co-authored-by: Johannes Schmoelder <j.schmoelder@fz-juelich.de>
Co-authored-by: Hannah Lanzrath <h.lanzrath@fz-juelich.de>
@jbreue16 jbreue16 deleted the feature/tractor branch June 19, 2024 13:04
@schmoelder
Copy link
Contributor Author

Congrats! 🎉

@hannahlanzrath
Copy link
Collaborator

hannahlanzrath commented Jun 19, 2024

thanks a lot for all your collective work on this guys, you're the coolest people 😎👌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants