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 arbitrary user quantities to logging #391

Closed
wants to merge 6 commits into from

Conversation

MTCam
Copy link
Member

@MTCam MTCam commented Jun 17, 2021

Follows onto #390, and adds an interface for arbitrary user quantities. Demonstrating use with CFL. In this one, the use is free to use the CFL field and visualize it, and the logger does not redundantly calculate it.

fixes #389

@MTCam MTCam changed the title generalize state logging and add cfl logging Add arbitrary user quantities to logging Jun 17, 2021
@MTCam MTCam added enhancement New feature or request y1 Flowing down to Y1 production labels Jun 17, 2021
class LogUserQuantity(LogQuantity):
"""Logging support for arbitrary user quantities."""

def __init__(self, name="user_quantity", value=None, user_function=None) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

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

Get rid of the user_function?

Copy link
Member Author

Choose a reason for hiding this comment

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

While the user_function is not needed for this particular quantity, it would be required for doing anything more complicated than just setting a simple value. This interface enables the user to specify a F(self._quantity) instead of a simple scalar value, without the need to extend logging with another user-defined quantity class.

Copy link
Member

Choose a reason for hiding this comment

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

I think passing in a function here might be a bit dangerous - how do you pass the function arguments, and how do you make sure they aren't stale? I'd remove this, and maybe think about creating a new class whenever we have a more clear use case.

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def __init__(self, name="user_quantity", value=None, user_function=None) -> None:
def __init__(self, name, unit, description="") -> None:

Copy link
Member Author

Choose a reason for hiding this comment

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

I think the burden of implementing the function with all its required data is on the user. This will be needed for anything more complicated than a simple value set. Consider this example, where the user wanted instead to perform the reduction on the inside of the logging class:

def get_domain_max(discr, field):
  from grudge.op import nodal_max
  return nodal_max(discr, "vol", field)

logmgr.add_quantity(UserLogQuantity(name="cfl", value=current_cfl,
                    description="inviscid CFL",
                    user_function=partial(get_domain_max, discr))

def pre_step_loop_body(step, t, dt, state):
  if do_viz:
   current_cfl = get_inviscid_cfl(blah, blah, blah)
   logmgr.set_quantity_value("cfl", current_cfl)

To me, this code is better than what we are doing currently (even in this PR) and is superior to the one where the discretization object (or the state, and/or the EOS) are implicitly used to calculate quantities under-the-covers.

self._value = value
self._uf = user_function

def set_quantity(self, value) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

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

Allow calling this via

logmgr.set_quantity(name, value)

so that you don't have to lug around the LogQuantity?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll take a crack at this unless this requires @matthiasdiener attention.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

if logmgr:
logmgr_add_device_name(logmgr, queue)
logmgr_add_device_memory_usage(logmgr, queue)
logmgr_add_many_discretization_quantities(logmgr, discr, dim,
extract_vars_for_logging, units_for_logging)
logmgr.add_quantity(LogCFL(discr, eos))

logmgr.add_quantity(my_log_quantity)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
logmgr.add_quantity(my_log_quantity)
logmgr.add_quantity(LogUserQuantity(name="cfl", value=current_cfl))

self._value = value
self._uf = user_function

def set_quantity(self, value) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

class LogUserQuantity(LogQuantity):
"""Logging support for arbitrary user quantities."""

def __init__(self, name="user_quantity", value=None, user_function=None) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

I think passing in a function here might be a bit dangerous - how do you pass the function arguments, and how do you make sure they aren't stale? I'd remove this, and maybe think about creating a new class whenever we have a more clear use case.

class LogUserQuantity(LogQuantity):
"""Logging support for arbitrary user quantities."""

def __init__(self, name="user_quantity", value=None, user_function=None) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def __init__(self, name="user_quantity", value=None, user_function=None) -> None:
def __init__(self, name, unit, description="") -> None:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request logging y1 Flowing down to Y1 production
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants