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 simple radiation model (Prad as a fraction of P_tot_in) #572

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

theo-brown
Copy link
Collaborator

@theo-brown theo-brown commented Nov 26, 2024

Add a simplified radiation sink model, P_rad = α*(P_aux + P_alpha + P_ohmic)

This is based on the functionality in JETTO:
image

Todo:

  • Calculate prad as a fraction of ptot
  • Add to outputs and plotting
  • Unit tests

@theo-brown theo-brown changed the title Add simple radiation model (Prad as a fraction of Ptot) Add simple radiation model (Prad as a fraction of P_tot_in) Nov 26, 2024
@theo-brown
Copy link
Collaborator Author

@Nush395 if you've got time, could you lend a hand with this? I have a couple of questions about implicit sources and sources that link back.

At the moment I'm finding that my implementation is nonzero when I inspect it during runtime but has no effect on the state. In the output, it is 0.

@Nush395
Copy link
Collaborator

Nush395 commented Nov 27, 2024

@Nush395 if you've got time, could you lend a hand with this? I have a couple of questions about implicit sources and sources that link back.

At the moment I'm finding that my implementation is nonzero when I inspect it during runtime but has no effect on the state. In the output, it is 0.

Yes for sure! Happy to answer questions, feel free to drop them on this PR or we can go over on a call if that's easier :)

@Nush395
Copy link
Collaborator

Nush395 commented Nov 27, 2024

@Nush395 if you've got time, could you lend a hand with this? I have a couple of questions about implicit sources and sources that link back.

At the moment I'm finding that my implementation is nonzero when I inspect it during runtime but has no effect on the state. In the output, it is 0.

Just took a quick look at the change. Just a sanity check, have you run the prad config with

'radiation_heat_sink': {'mode': 'model_based'}

?
(As the default mode that you inherit from the RuntimeParams is set to ZERO.)

@theo-brown
Copy link
Collaborator Author

Ah, thanks for spotting that. That would be why it wasn't being used! I'll do that and then see where I get to. Sorry for not spotting the obvious thing!

@Nush395
Copy link
Collaborator

Nush395 commented Nov 27, 2024

Ah, thanks for spotting that. That would be why it wasn't being used! I'll do that and then see where I get to. Sorry for not spotting the obvious thing!

No worries at all, I've run into that gotcha myself!

@theo-brown
Copy link
Collaborator Author

theo-brown commented Nov 27, 2024

As of 69f5ada, unit tests fail because I've added a term to post_processed_outputs that is not present in all of the current .nc files. Hence, all test data will need to be regenerated. Is there a speedy way of doing this?

@Nush395
Copy link
Collaborator

Nush395 commented Nov 27, 2024

As of 69f5ada, unit tests fail because I've added a term to post_processed_outputs that is not present in all of the current .nc files. Hence, all test data will need to be regenerated. Is there a speedy way of doing this?

There is, there is a run_and_save_all_benchmarks.py script that we use. See the bottom of https://torax.readthedocs.io/en/latest/contribution_tips.html#contribution-tips that @jcitrin recently added to. (Will also make this a bit more visible, if you have suggestions on where this should be please let us know!)

@theo-brown
Copy link
Collaborator Author

@Nush395 it now makes sense to ask my questions!

  • Should source tests be written on a per-source basis, or use inheritance? See e.g. BootstrapCurrentSourceTest (which is a SourceTestCase whose test_extraction_of_relevant_profile_from_output is identical to that of other psi sources), vs FusionHeatSourceTest (which is an IonElSourceTestCase to avoid reimplementing such functions for all Te + Ti sources).
  • Where is the OhmicHeatSource tested? As far as I can tell it's the only other source that has links_back=True and I was hunting around to try and copy its test pattern.

Required regenerating some integration tests with new Prad output
Use source_builder in all tests, except from BootstrapCurrentSource and QeiSource
@theo-brown theo-brown marked this pull request as ready for review November 27, 2024 15:41
@theo-brown
Copy link
Collaborator Author

For the time being I've gone for only inheriting from SourceTestCase, which means:

  • Inherit
    • test_expected_mesh_states
    • test_runtime_params_builds_dynamic_params
  • Reimplement
    • test_extraction_of_relevant_profile_from_output
    • test_invalid_source_types_raise_errors
    • test_source_value

I couldn't quite figure out why test_extraction_of_relevant_profile_from_output and test_invalid_source_types_raise_errors weren't implemented in the parent class - it seems to me that they should be functions of the source properties only? Regardless, this seemed to be the pattern implemented by most other sources, so I went with that.

@Nush395
Copy link
Collaborator

Nush395 commented Nov 27, 2024

@Nush395 it now makes sense to ask my questions!

Hey Theo, sorry for the slow response on this.

  • Should source tests be written on a per-source basis, or use inheritance? See e.g. BootstrapCurrentSourceTest (which is a SourceTestCase whose test_extraction_of_relevant_profile_from_output is identical to that of other psi sources), vs FusionHeatSourceTest (which is an IonElSourceTestCase to avoid reimplementing such functions for all Te + Ti sources).

In the general case I'd advise inheriting from SourceTestCase as that has some basic test cases relevant to all sources in general. If your source only affects a single profile there is also the SingleProfileSourceTestCase https://github.com/google-deepmind/torax/blob/main/torax/sources/tests/test_lib.py#L113 that has more specialised tests for sources that only affect a single source (as yours does).

  • Where is the OhmicHeatSource tested? As far as I can tell it's the only other source that has links_back=True and I was hunting around to try and copy its test pattern.

That's a good question. Taking a quick look now it doesn't seem there is one which is something we can rectify. Thanks for raising this.

@Nush395
Copy link
Collaborator

Nush395 commented Nov 27, 2024

I couldn't quite figure out why test_extraction_of_relevant_profile_from_output and test_invalid_source_types_raise_errors weren't implemented in the parent class - it seems to me that they should be functions of the source properties only? Regardless, this seemed to be the pattern implemented by most other sources, so I went with that.

For test_invalid_source_types_raise_errors that is implemented in the SingleProfileSourceTestCase and you are right for the test_extraction_of_relevant_profile_from_output this is likely a legacy thing that could be tidied up and pushed into the parent class now. I can TAL at doing that and doing some test tidying up.

@theo-brown
Copy link
Collaborator Author

I can TAL at doing that and doing some test tidying up.

I'm more than happy to tackle this in a separate PR if you want to have a look at the ohmic source? Unless you'd rather do both!

@Nush395
Copy link
Collaborator

Nush395 commented Nov 28, 2024

I can TAL at doing that and doing some test tidying up.

I'm more than happy to tackle this in a separate PR if you want to have a look at the ohmic source? Unless you'd rather do both!

That would be great if you have time, thanks!

Copy link
Collaborator

@jcitrin jcitrin left a comment

Choose a reason for hiding this comment

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

Looks really great, thanks!

Appreciate also the extensive testing + extensions to the tests.

Copy link
Collaborator

Choose a reason for hiding this comment

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

  1. Not sure there's much point in making an example config out of a single feature?

  2. Our standard pattern is to make a new integration test in tests/tests_data with new features for regression and integration testing.

Suggest to remove it here, make a new integration test (to add to tests/sim.py also) based on one of the standard cases like test_iterhybrid_predictor_corrector

Copy link
Collaborator

Choose a reason for hiding this comment

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

a bit of a nit:

radiation_heat_sink isn't specific enough, it could refer to cyclotron, bremsstrahlung, e.g.

How about impurity_radiation_heat_sink ?

Was also thinking about line_radiation_heat_sink, but some radiation models like Mavrin polynomials include both line radiation + cremsstrahlung, so maybe ok to specify just "impurity"

) -> jax.Array:
"""Model function for radiation heat sink.

In this model, a fixed % of the total power input to the temp_el equation is lost."""
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: confusing wording. Maybe "A fixed % of the total power input is lost as a sink of the temp_el equation"


Qtot_in = jnp.sum(jnp.stack(source_profiles), axis=0)
Ptot_in = math_utils.cell_integration(Qtot_in * geo.vpr, geo)
Vtot = math_utils.cell_integration(geo.vpr, geo)
Copy link
Collaborator

Choose a reason for hiding this comment

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

can just use geo.volume_face[-1] . It will differ by a tiny amount (like 0.01% or so, depending on the grid and geometry resolution) from this cell_integration, since geo.volume_face comes directly from the vpr integration on the original geometry grid, as opposed to the interpolation on the TORAX cell grid.

# Manually remove sources that will not be summed
sources_to_sum = source_models.temp_el_sources | source_models.temp_ion_sources
sources_to_sum.pop(SOURCE_NAME, None)
sources_to_sum.pop(bremsstrahlung_heat_sink.SOURCE_NAME, None)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can easily imagine a bug where we add more heat sinks and forget to update this function.

Can we guard against it somehow? Maybe check all remaining keys if they contain the substring 'sink' and then raise an error. This depends on having the discipline to call all new sinks "something_heat_sink", but it's better than nothing.

Copy link
Collaborator

Choose a reason for hiding this comment

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

can remove

Copy link
Collaborator

Choose a reason for hiding this comment

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

can remove

Copy link
Collaborator

Choose a reason for hiding this comment

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

can remove

Copy link
Collaborator

Choose a reason for hiding this comment

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

how come this needed to be replaced?

# and summing over *both* ion and electron heating

def get_temp_el_profile(source_name: str, source: source_lib.Source) -> jax.Array:
# TODO: Currently this recomputes the profile for each source, which is inefficient
Copy link
Collaborator

Choose a reason for hiding this comment

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

agree. We will prioritize changing the pattern such that this won't happen.

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