Skip to content

Conversation

@av-novikov
Copy link
Contributor

@av-novikov av-novikov commented Apr 24, 2025

cycleNumber is required for execute/output/collect calls in PyHistoryCollection.cpp, PyHistoryOutput.cpp, PyVTKOutput.cpp and PySolver.cpp. Currently, it is not passed from Python, but awkwardly calculated as int cycleNumber = int(round( time/dt )); which result in, for example, wrong indexation of VTK snapshots in case of dynamically changing timestep.

This PR support receiving of cycleNumber from Python in affected C++ calls.
Goes with geosPythonPackages: PR89.

@av-novikov av-novikov changed the title Receive cycleNumber for Python bindings in output/execute/collect calls feat: Receive cycleNumber for Python bindings in output/execute/collect calls Apr 24, 2025
@av-novikov av-novikov self-assigned this Apr 24, 2025
@av-novikov av-novikov added the ci: run code coverage enables running of the code coverage CI jobs label Apr 24, 2025
@codecov
Copy link

codecov bot commented Apr 24, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 56.66%. Comparing base (078f90d) to head (34d9128).
Report is 19 commits behind head on develop.

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #3631   +/-   ##
========================================
  Coverage    56.66%   56.66%           
========================================
  Files         1217     1217           
  Lines       105126   105126           
========================================
  Hits         59567    59567           
  Misses       45559    45559           

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Victor-M-Gomes
Copy link

Hello Alexander, is it possible to have a check for cycleNumber? To make sure it has been parsed? That would avoid obliging us to modify all previous python codes.

Thanks.

static PyObject * collect( PyHistoryCollection * self, PyObject * args )
{
  VERIFY_NON_NULL_SELF( self );
  VERIFY_INITIALIZED( self );

  double time;
  double dt;
  int cycleNumber;
  int parsed_cycleNumber = 0; // Flag to track if cycleNumber was parsed

  if( !PyArg_ParseTuple( args, "ddi", &time, &dt, &cycleNumber ) )
  {
    // If parsing fails, it might be due to 'cycleNumber' not being provided.
    // Attempt to parse with only 'time' and 'dt'.
    if( !PyArg_ParseTuple( args, "dd", &time, &dt ) )
    {
      // If that also fails, then the initial arguments were incorrect.
      return nullptr;
    }
    // If parsing with "dd" succeeded, then 'cycleNumber' was not provided.
    cycleNumber = static_cast<int>(round( time / dt ));
    parsed_cycleNumber = 0; // Indicate that cycleNumber was calculated
  } else {
    parsed_cycleNumber = 1; // Indicate that cycleNumber was successfully parsed
  }

  geos::DomainPartition & domain = self->group->getGroupByPath< DomainPartition >( "/Problem/domain" );

  try
  {
    self->group->execute( time, dt, cycleNumber, 0, 0, domain );

@av-novikov
Copy link
Contributor Author

av-novikov commented Apr 25, 2025

Hello Alexander, is it possible to have a check for cycleNumber? To make sure it has been parsed? That would avoid obliging us to modify all previous python codes.

Thanks.

static PyObject * collect( PyHistoryCollection * self, PyObject * args )
{
  VERIFY_NON_NULL_SELF( self );
  VERIFY_INITIALIZED( self );

  double time;
  double dt;
  int cycleNumber;
  int parsed_cycleNumber = 0; // Flag to track if cycleNumber was parsed

  if( !PyArg_ParseTuple( args, "ddi", &time, &dt, &cycleNumber ) )
  {
    // If parsing fails, it might be due to 'cycleNumber' not being provided.
    // Attempt to parse with only 'time' and 'dt'.
    if( !PyArg_ParseTuple( args, "dd", &time, &dt ) )
    {
      // If that also fails, then the initial arguments were incorrect.
      return nullptr;
    }
    // If parsing with "dd" succeeded, then 'cycleNumber' was not provided.
    cycleNumber = static_cast<int>(round( time / dt ));
    parsed_cycleNumber = 0; // Indicate that cycleNumber was calculated
  } else {
    parsed_cycleNumber = 1; // Indicate that cycleNumber was successfully parsed
  }

  geos::DomainPartition & domain = self->group->getGroupByPath< DomainPartition >( "/Problem/domain" );

  try
  {
    self->group->execute( time, dt, cycleNumber, 0, 0, domain );

Dear @Victor-M-Gomes, thanks for checking!

  1. Do I understand you correctly that you suggest to keep option to provide 2 arguments (time, dt) for the support of legacy code outside both repos?
  2. Do you understand that it leaves a loophole for mistakes at least in output every time you change timestep?
  3. Are you talking only about PyHistoryCollection or all affected classes? My concern is that wrong indexation in execute call may lead to mistakes beyond output.

I do not mind if you insist, but it is not a big change to support and cycleNumber = static_cast<int>(round( time / dt )) is ridiculous to me.

@Victor-M-Gomes
Copy link

Hello Alexander, is it possible to have a check for cycleNumber? To make sure it has been parsed? That would avoid obliging us to modify all previous python codes.
Thanks.

static PyObject * collect( PyHistoryCollection * self, PyObject * args )
{
  VERIFY_NON_NULL_SELF( self );
  VERIFY_INITIALIZED( self );

  double time;
  double dt;
  int cycleNumber;
  int parsed_cycleNumber = 0; // Flag to track if cycleNumber was parsed

  if( !PyArg_ParseTuple( args, "ddi", &time, &dt, &cycleNumber ) )
  {
    // If parsing fails, it might be due to 'cycleNumber' not being provided.
    // Attempt to parse with only 'time' and 'dt'.
    if( !PyArg_ParseTuple( args, "dd", &time, &dt ) )
    {
      // If that also fails, then the initial arguments were incorrect.
      return nullptr;
    }
    // If parsing with "dd" succeeded, then 'cycleNumber' was not provided.
    cycleNumber = static_cast<int>(round( time / dt ));
    parsed_cycleNumber = 0; // Indicate that cycleNumber was calculated
  } else {
    parsed_cycleNumber = 1; // Indicate that cycleNumber was successfully parsed
  }

  geos::DomainPartition & domain = self->group->getGroupByPath< DomainPartition >( "/Problem/domain" );

  try
  {
    self->group->execute( time, dt, cycleNumber, 0, 0, domain );

Dear @Victor-M-Gomes, thanks for checking!

1. Do I understand you correctly that you suggest to keep option to provide 2 arguments (time, dt) for the support of legacy code outside both repos?

2. Do you understand that it leaves a loophole for mistakes at least in output every time you change timestep?

3. Are you talking only about PyHistoryCollection or all affected classes? My concern is that wrong indexation in execute call may lead to mistakes beyond output.

I do not mind if you insist, but it is not a big change to support and cycleNumber = static_cast<int>(round( time / dt )) is ridiculous to me.

I see. Nevermind then. When the time comes we will make the necessary changes on our side.

@rrsettgast rrsettgast added ci: run CUDA builds Allows to triggers (costly) CUDA jobs ci: run integrated tests Allows to run the integrated tests in GEOS CI and removed ci: run code coverage enables running of the code coverage CI jobs labels May 15, 2025
@rrsettgast rrsettgast merged commit 5a65081 into develop May 17, 2025
25 of 26 checks passed
@rrsettgast rrsettgast deleted the feature/anovikov/cyclenumber_from_python branch May 17, 2025 20:58
danielemoretto44 pushed a commit that referenced this pull request Sep 22, 2025
…ct calls (#3631)

* Receive cycleNumber from Python in output/execute/collect calls
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci: run CUDA builds Allows to triggers (costly) CUDA jobs ci: run integrated tests Allows to run the integrated tests in GEOS CI flag: ready for review type: feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants