Skip to content

Commit

Permalink
Add a HOOK capable of updating plugin variables only once at the end …
Browse files Browse the repository at this point in the history
…of the time step computation (#366)

* update hook_specs update_plugins_secondary_variables_time_explicit

* update documentation

Co-authored-by: Gustavo G. Ribeiro <ggrbill@users.noreply.github.com>

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Gustavo G. Ribeiro <ggrbill@users.noreply.github.com>
  • Loading branch information
3 people authored Mar 14, 2024
1 parent 834ffe5 commit de60c45
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 2 deletions.
3 changes: 3 additions & 0 deletions docs/source/plugins/06_solver_hooks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ is called, but if it is running the `first time step`
:py:func:`HOOK_UPDATE_PLUGINS_SECONDARY_VARIABLES_ON_FIRST_TIMESTEP<alfasim_sdk._internal.hook_specs.update_plugins_secondary_variables_on_first_timestep>`
is called before. It is necessary because usually during the `first time step` some initialization tasks are needed. Then,
if the plugin needs to initialize with some value that is different from the initial ``nan`` value, this hook is the place to do that.
Another possibility is to update secondary variables explicitly on timestep. For that :py:func:`HOOK_UPDATE_PLUGINS_SECONDARY_VARIABLES_TIME_EXPLICIT<alfasim_sdk._internal.hook_specs.update_plugins_secondary_variables_time_explicit>` can be used and it will be called once at the end of the timestep. This hook is important in situations where the secondary variable doesn't affect the solution or when secondary variable computations are extremely heavy, in which computational time would be prohibited.

.. note::
Different from plugin internal data, the secondary variables registered by plugins are allocated, deallocated and
Expand All @@ -93,6 +94,8 @@ if the plugin needs to initialize with some value that is different from the ini

.. autofunction:: alfasim_sdk._internal.hook_specs.update_plugins_secondary_variables_on_first_timestep

.. autofunction:: alfasim_sdk._internal.hook_specs.update_plugins_secondary_variables_time_explicit

The |alfasim|'s Solver is divided in two *non-linear solvers* solvers that will solve different group of equations. The first one is
the `hydrodynamic solver` which solves the Mass Conservation of fields, Momentum Conservation of layers and Energy Conservation
equations all together for all elements in the network. The second one is the `Tracer Solver` which solves the Mass Conservation
Expand Down
63 changes: 61 additions & 2 deletions src/alfasim_sdk/_internal/hook_specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def update_plugins_secondary_variables(ctx: "void*") -> "int":
int errcode = -1;
int size_U = -1;
int size_E = -1;
int liq_id = -1;
int oil_id = -1;
errcode = alfasim_sdk_api.get_field_id(
ctx, &oil_id, "oil");
double* vel;
Expand All @@ -152,7 +152,7 @@ def update_plugins_secondary_variables(ctx: "void*") -> "int":
TimestepScope::CURRENT
}
errcode = alfasim_sdk_api.get_simulation_array(
ctx, &vel, (char*) "U", Fields_OnFaces, liq_id, &size_U);
ctx, &vel, (char*) "U", Fields_OnFaces, oil_id, &size_U);
double* kinetic_energy;
char* name = "kinetic_energy_of_oil";
int global_idx = 0;
Expand All @@ -178,6 +178,64 @@ def update_plugins_secondary_variables(ctx: "void*") -> "int":
"""


def update_plugins_secondary_variables_time_explicit(ctx: "void*") -> "int":
"""
**c++ signature** : ``HOOK_UPDATE_PLUGINS_SECONDARY_VARIABLES_TIME_EXPLICIT(void* ctx)``
Internal simulator hook to update plugin's secondary variables time explicit.
This is called only once at the end of ALFAsim's update internal secondary variables workflow.
:param ctx: ALFAsim's plugins context
:returns: Return OK if successful or anything different if failed
Example of usage:
.. code-block:: c++
:linenos:
:emphasize-lines: 1
HOOK_UPDATE_PLUGINS_SECONDARY_VARIABLES_TIME_EXPLICIT(ctx)
{
int errcode = -1;
int size_U = -1;
int size_E = -1;
int liq_id = -1;
errcode = alfasim_sdk_api.get_field_id(
ctx, &oil_id, "oil");
double* vel;
VariableScope Fields_OnFaces = {
GridScope::FACE,
MultiFieldDescriptionScope::FIELD,
TimestepScope::CURRENT
}
errcode = alfasim_sdk_api.get_simulation_array(
ctx, &vel, (char*) "U", Fields_OnFaces, liq_id, &size_U);
double* kinetic_energy;
char* name = "kinetic_energy_of_oil";
int global_idx = 0;
errcode = alfasim_sdk_api.get_plugin_variable(
ctx,
(void**) (&kinetic_energy),
name,
global_idx,
TimestepScope::CURRENT,
&size_E);
if (size_U != size_E){
return OUT_OF_BOUNDS;
}
for (int i =0; i < size_U; ++i){
kinetic_energy[i] = vel[i] * vel[i] / 2.;
}
return OK;
}
In the example above the variable ``kinetic_energy_of_oil`` was registered as a global variable, but its value is
obtained for `oil field` and only at the end of the time steps' linear solver (explicit approach). If this
variable would be calculated to all fields then the ``global_idx`` would be substituted by ``field_idx`` and it
would be performed to each `field`.
"""


def update_plugins_secondary_variables_on_first_timestep(ctx: "void*") -> "int":
"""
**c++ signature** : ``HOOK_UPDATE_PLUGINS_SECONDARY_VARIABLES_ON_FIRST_TIMESTEP(void* ctx)``
Expand Down Expand Up @@ -1985,6 +2043,7 @@ def update_internal_deposition_layer(
finalize,
# Update secondary variables registered by plugin
update_plugins_secondary_variables_on_first_timestep,
update_plugins_secondary_variables_time_explicit,
update_plugins_secondary_variables,
update_plugins_secondary_variables_on_tracer_solver,
# Calculate source terms
Expand Down

0 comments on commit de60c45

Please sign in to comment.