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

Clean-up for PinTSimE + Update for SwitchEstimator (Preparation for PR for paper stuff) #362

Merged
merged 16 commits into from
Oct 25, 2023

Conversation

lisawim
Copy link
Collaborator

@lisawim lisawim commented Oct 6, 2023

Wui, finished!

For the submitted paper I created a folder in the PinTSimE project folder containing

  • a readme of how the plots in the paper can be reproduced with all necessary information of the parameters,
  • a Python script to be executed to generate the plots.

The paper contains two new discontinuous DAE models: a test DAE DiscontinuousTestDAE containing an exact solution and an exact event time, and the more realistic one, WSCC9BusSystem a power system case where @junjie-zh and I spend several weeks to implement this one in pySDC. The latter one contains 57 equations.. Thus a solve is very expensive (also in view of computing time). Executing the script paper_plots.py takes approximately nine hours (ugh!) which is the reason why I disabled it in the script.. But I write tests for both DAE classes to ensure that everything goes right.

SwitchEstimator got one more update: I added Lagrange interpolation to interpolate the dynamics of the state function. This required complete rewriting of the tests already contained.

Since I'm not satisfied with the total mess in the PinTSimE project especially in the files to the battery models, I rewrite almost everything to have more clarification of what and how is done there. But the most important thing: readability has improved significantly. At least I hope so.. For the numerical solution a dictionary u_num is created which provides all the important stuff to generate beautiful plots. There is also the possibility to consider different number of collocation nodes. The old plots for the battery model does only make sense to plot stuff for one coll. node, otherwise they will be "overloaded".. But such a dictionary makes it easier to implement plots containing results for more than one collocation node, which is for instance already done in the plots for the paper.

Next thing.. The Python script for generating the paper plots paper_plots.py is not yet consistent with the stuff I did for the battery models (I mean the script has still another structure to compute the dictionary for the numerical solution, bla bla ..) But I don't want to change it now. I left this for the (far) future..

Then I used the possibility to also clean up the files for piline and buck_converter and updated their hardcoded solutions. I updated the playground EnergyGrids as well and removed the log data files there, because they are not needed anymore.

Since pypower is needed for the problem class WSCC9BusSystem, I guess environment-base.yml has to be updated which I did.

Hm, I hope I forgot nothing..

I know this is a big PR and I really apologize for that, but I would really appreciate it if you could take a look. Thank you so much for your time in advance! I guess you don't have to take a look at the PinTSimE stuff, and the playground, but rather for the stuff for paper.

@pancetta
Copy link
Member

Please merge master, I fixed two dependency issues there.

Copy link
Contributor

@brownbaerchen brownbaerchen left a comment

Choose a reason for hiding this comment

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

This is a pretty big PR, so I did not go through everything in detail. Particularly, I did not look at plotting at all.
At this point, I am not 100% sure what the functionality is that you are after, so I did not go into detail to understand what the functions are doing. I trust you that you made sure the functionality is what you want and that the tests are meaningful.

I think you greatly improved on readability in many places. Good job!
I do have some minor comments, concerns, though. The most important one being the filtering of recomputed values, I think.

if V_ref is None and ncapacitors == 1:
V_ref = np.array([1.0])
else:
assert (alpha > V_ref[k] for k in range(n)), 'Please set "alpha" greater than values of "V_ref"'
Copy link
Contributor

Choose a reason for hiding this comment

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

To be honest, I don't totally know what happens here. I usually use all or any for asserting things like this. Since black did not complain, this must be valid. But please be sure that it does what you want it to do and consider adding all to improve readability by being more explicit.

Also, this line should come after the check if V_ref is an array at all to avoid confusing error messages.

if C is None:
C = np.array([1.0])
else:
assert type(C) == np.ndarray, '"C" needs to be an np.ndarray'
assert np.shape(C)[0] == n, 'Number of capacitance values needs to be equal to number of condensators'
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: capacitors instead of condensators

assert alpha > V_ref[0], 'Please set "alpha" greater than values of "V_ref"'
assert type(V_ref) == np.ndarray, '"V_ref" needs to be an np.ndarray'
assert np.shape(V_ref)[0] == n, 'Number of reference values needs to be equal to number of condensators'
assert V_ref[0] > 0, 'Please "V_ref" greater than 0'
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do you check these things here? You inherit from the battery class, which I believe fixes the number of capacitors to 1. And this, in turn, inherits from battery_n_capticitors, which performs these tests anyways, making them redundant here.
I suggest removing these tests here and, if you want, adding an __init__ to battery that only makes sure that n_capacitors == 1 and calls the super init.

The only thing you need here is the variables for counting Newton iterations, which you should ideally replace with the WorkCounters for consistent interfaces among problems.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, you are right!

WorkCounters everywhere! I'll add that!

h = 2 * y - 100
f = self.dtype_f(self.init)

f_before_event = (
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do you compute both and then check which to assign to f[:] instead of computing while assigning? It probably makes little difference for speed, but aids readability in my opinion.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I also add that for readability, but I agree with you. Only one of these f is necessary, hence no need to compute both at every time!

Exact solution.
"""

assert t >= 1, 'ERROR: u_exact only valid for t>=1'
Copy link
Contributor

Choose a reason for hiding this comment

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

How do you get the initial conditions? Do you have to start at t=1? Also, I suggest replacing valid with available.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, it's possible to compute the initial condition starting at t=1. but also at a later time. I'll adapt that!

# dangerous! in case of nonmoving state function after event, event time could be distorted!
t_switch = t_interp[0]
boundary = 'left'
self.log(f"Is already close enough to the {boundary} end point!", S)
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe this message could be a bit more elaborate.

elif abs(state_function[-1]) <= self.params.tol_zero:
boundary = 'right'
t_switch = t_interp[-1]
else:
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this ever be entered? The above statement is if either is close to zero you go here and this you enter only if neither is close to zero...?



@pytest.mark.base
def test_DiscontinuousTestDAE_SDC():
Copy link
Contributor

Choose a reason for hiding this comment

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

you can make M and argument of this function and add a decorator @pytest.mark.parametrize('M', [2, 3, 4, 5]) to separate this into different tests. I find this a bit nicer because the error handling will be more precise. Maybe the tests only failed for 3 nodes, for instance.

5: 0.0101,
}

for M in [2, 3, 4, 5]:
Copy link
Contributor

Choose a reason for hiding this comment

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

You can again make this an argument of the function if you want.

@@ -357,3 +391,47 @@ def newton(x0, p, fprime, newton_tol, newton_maxiter):
print(msg)

return root


class LagrangeInterpolation(object):
Copy link
Contributor

Choose a reason for hiding this comment

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

You could consider using Thibaut's interpolation stuff, which is well tested. I am not sure how the two things compare on speed. With Thibaut's stuff, you have to generate a new interpolation matrix every time you want to interpolate to a new time and multiply this with the solution vector. But this might be faster than generating the Lagrange polynomials from scratch every time. Regardless, building on well tested stuff is always nice.

@brownbaerchen
Copy link
Contributor

I am a bit concerned about pypower, as it is no longer actively maintained and is tested only until python 3.9. Maybe we should do another environment for your stuff? That would also speed up the GitHub CI by parallelising the pipeline some more. What do you think, @pancetta?

@pancetta
Copy link
Member

pancetta commented Oct 16, 2023

Yeah, no, I'd rather not introduce another dependency, unless there is a strong need for this. And if we introduce another dependency, this has to work (currently) with versions 3.7-3.10, later also 3.11 and 3.12.

@brownbaerchen
Copy link
Contributor

Yeah, no, I'd rather not introduce another dependency, unless there is a strong need for this.

What do you mean? You don't want another dependency or not another environment? The tests are currently failing because of the missing dependency and I have no idea how much work it would be to replace this by hand or by scipy or whatever.

@lisawim
Copy link
Collaborator Author

lisawim commented Oct 16, 2023

Ok, and how should I deal with the ModuleNotFoundError (from pypower) raised in one of the failed tests? Do I have to add it to etc/environment-base.yml?

@pancetta
Copy link
Member

How important is this dependency? Is this a "nice to have" or a "must have, no other suitable option"? Introducing another dependency file (environment-bla.yml) is only intended for larger packages like petsc. Introducting another dependency in the base environment needs proper testing and we got to be sure that this will not backfire (e.g. when going to newer python versions).

@junjie-zh
Copy link
Contributor

The pypower package is only needed for power system test cases, it can be used to create some benchmark networks and in general calculating the initial values (nodal voltages).

@junjie-zh
Copy link
Contributor

There is a workaround: I can also implement the WSCC9bus network hard-codded in this problem file, so then the dependency can be removed.

@pancetta
Copy link
Member

Oh, yes please!! I was about to write a lengthy description what we need to do if we want to keep pypower in..

@lisawim
Copy link
Collaborator Author

lisawim commented Oct 16, 2023

Hm, I know that we also tried another packages for computing the initial conditions. But in the end, these are only fixed values coming from the YBus providing all the data for the network. So, we can do a bit of magic here by defining the YBus as hardcoded dictionary as it is also done for get_initial_Ybus() and get_event_Ybus() such that we do not need to import the pypower anymore. What do you think @pancetta @junjie-zh ?

@lisawim
Copy link
Collaborator Author

lisawim commented Oct 16, 2023

Yes, what I wrote.

@pancetta
Copy link
Member

If you manage to do this without any other (new) dependency, I'm happy!

@pancetta
Copy link
Member

You may want to consider splitting this example from the PR, though. This is a big PR and maybe the big power grid examples "deserves" its own PR.

@lisawim
Copy link
Collaborator Author

lisawim commented Oct 16, 2023

So, this means closing this PR and request new (at least two) ones?

@pancetta
Copy link
Member

You could (I'm just suggesting) remove the big example here and add it to a new one.

@brownbaerchen
Copy link
Contributor

brownbaerchen commented Oct 16, 2023

So, this means closing this PR and request new (at least two) ones?

You don't have to close this one. Just add a new PR with only the problem and then you can decide if you want to remove the problem from this PR (which you can do without closing) or if you want to wait until we merge the other PR and then you can merge master here again.

I like to do

git checkout master
git checkout -b big_problem

and then for each file that you need:

git checkout paper_stuff -- <path_to_file_for_big_problem>

Then try if the tests work, maybe adapt a few things, commit, push, PR.

You can also use this as a stash for later, though. What Robert suggested may be simpler.

@lisawim
Copy link
Collaborator Author

lisawim commented Oct 22, 2023

I decided not to move the big power system example to a separate PR, but the whole paper stuff, and the clean-up here (together with an updated version of the switch estimator is then a preparation to this PR). Before merging I'll also have a look at the Lagrange Interpolation in the switch estimator at some time..

@lisawim lisawim changed the title Update for PinTSimE + Stuff for paper for PSCC 2024 Clean-up for PinTSimE + Update for SwitchEstimator (Preparation for PR for paper stuff) Oct 22, 2023
@brownbaerchen
Copy link
Contributor

brownbaerchen commented Oct 23, 2023

Do you want me to read through the code again? Anything new besides the things you mentioned and I complained about earlier?

@pancetta
Copy link
Member

Please merge from master, again.

@codecov
Copy link

codecov bot commented Oct 24, 2023

Codecov Report

Attention: 5 lines in your changes are missing coverage. Please review.

Comparison is base (f5658fc) 73.26% compared to head (e22f87d) 72.55%.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #362      +/-   ##
==========================================
- Coverage   73.26%   72.55%   -0.71%     
==========================================
  Files         270      269       -1     
  Lines       23097    22330     -767     
==========================================
- Hits        16922    16202     -720     
+ Misses       6175     6128      -47     
Files Coverage Δ
pySDC/projects/PinTSimE/battery_model.py 100.00% <100.00%> (ø)
pySDC/projects/PinTSimE/buck_model.py 100.00% <100.00%> (ø)
pySDC/projects/PinTSimE/discontinuous_test_ODE.py 100.00% <100.00%> (+1.14%) ⬆️
pySDC/projects/PinTSimE/estimation_check.py 100.00% <100.00%> (+12.71%) ⬆️
pySDC/projects/PinTSimE/hardcoded_solutions.py 100.00% <100.00%> (ø)
pySDC/projects/PinTSimE/piline_model.py 100.00% <100.00%> (ø)
pySDC/projects/PinTSimE/switch_estimator.py 93.39% <96.77%> (-4.34%) ⬇️
pySDC/implementations/problem_classes/Battery.py 96.38% <83.33%> (+0.25%) ⬆️

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@pancetta
Copy link
Member

Anyone wants to have another look here? Are there still open todos for this PR?

@lisawim
Copy link
Collaborator Author

lisawim commented Oct 24, 2023

I also want to have a look at the Lagrange interpolation and probably use @tlunet's stuff. But I already used the current version of the Switch Estimator (not including @tlunet's stuff yet) for producing the results for the paper, and I didn't test yet if this would lead to the same results. In order to reproduce the plots from the paper I would feel more comfortable if this PR would be merged and then I'll deal with the Lagrange interpolation from @tlunet in a PR after merge the paper stuff. Is that fine for you?

And I also don't know if @brownbaerchen has further compliants. I changed all requested things from him. From my side he shouldn't have another look at that.

@brownbaerchen
Copy link
Contributor

LGTM

Thibaut's stuff should give the same result. Both is Lagrange interpolation, just with a different interface. But from my point of view it's fine to merge this now.

@pancetta pancetta merged commit 83415ca into Parallel-in-Time:master Oct 25, 2023
24 of 25 checks passed
pancetta pushed a commit that referenced this pull request Nov 9, 2023
* Added README for paper stuff

* Lagrange interpolation for SwitchEstimator

* Clean-up for project, i.e., merge stuff for all battery models together

* add WSCC9Bus DAE test case

* PascalCase for functions + possibility of computing solution for different number of coll. nodes + updated hardcoded solutions

* Added stuff for paper with new problem DTestDAE and corresponding tests for both DAE models from paper

* Updated tests with hardcoded solutions for PinTSimE

* Clean-up also for piline+buck_converter, and update for playground

* Minor changes + black..

* Update README for paper + add pypower to environment-base.yml

* ?

* Removed stuff for paper (will moved to another PR)

* Requested changes

* add WSCC09 test case with cleaned dependency

* Added test for WSCC9

* fix WSCC9 case, minor error fix

* Added discontinuous test DAE + test and black for WSCC9

* Minor changes for DiscontinuousTestDAE

* Added folder for paper stuff

* Removed generated plots

* Added commit to README to be used for generating paper stuff

* Requested changes

* WIP: add threeInverterSystem

* Removed class again (not part of this PR)

* Shortened test for WSCC9 bus test case

* Oh black.. how I could forget you..?

* Renamed test

* One more test for WSCC9

---------

Co-authored-by: Junjie Zhang <junjie.zhang1@rwth-aachen.de>
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.

4 participants