Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions framework/include/userobjects/SolutionUserObjectBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,17 @@ class SolutionUserObjectBase : public GeneralUserObject
/// Map from block names to block IDs. Read from the ExodusII file
std::map<SubdomainID, SubdomainName> _block_id_to_name;

// All the caches are duplicated between the before-timestep and after-timestep mesh functions
/// Cached points
mutable Point _cached_p = Point(std::numeric_limits<Real>::max(), 0., 0.);
mutable Point _cached_p2 = Point(std::numeric_limits<Real>::max(), 0., 0.);
/// Cached subdomain ids
mutable std::set<subdomain_id_type> _cached_subdomain_ids;
mutable std::set<subdomain_id_type> _cached_subdomain_ids2;
/// Cached values
mutable DenseVector<Number> _cached_values;
mutable DenseVector<Number> _cached_values2;

private:
static Threads::spin_mutex _solution_user_object_mutex;
};
47 changes: 37 additions & 10 deletions framework/src/userobjects/SolutionUserObjectBase.C
Original file line number Diff line number Diff line change
Expand Up @@ -292,16 +292,15 @@ SolutionUserObjectBase::readExodusII()
{
if (std::find(all_nodal.begin(), all_nodal.end(), var_name) != all_nodal.end())
_nodal_variables.push_back(var_name);
if (std::find(all_elemental.begin(), all_elemental.end(), var_name) != all_elemental.end())
else if (std::find(all_elemental.begin(), all_elemental.end(), var_name) !=
all_elemental.end())
_elemental_variables.push_back(var_name);
if (std::find(all_scalar.begin(), all_scalar.end(), var_name) != all_scalar.end())
// Check if the scalar matches any field variables, and ignore the var if it does. This
// means its a Postprocessor.
if (std::find(begin(_nodal_variables), end(_nodal_variables), var_name) ==
_nodal_variables.end() &&
std::find(begin(_elemental_variables), end(_elemental_variables), var_name) ==
_elemental_variables.end())
_scalar_variables.push_back(var_name);
else if (std::find(all_scalar.begin(), all_scalar.end(), var_name) != all_scalar.end())
// We checked other variables types first, so if a postprocessor has the same name as a
// field variable, it won't get loaded as a scalar variable
_scalar_variables.push_back(var_name);
else
paramError("system_variables", "Variable '" + var_name + "' was not found in Exodus file");
}
}
else
Expand Down Expand Up @@ -572,6 +571,10 @@ SolutionUserObjectBase::initialSetup()
_local_variable_index[name] = i;
}

// If the start time is not the same as in the exodus file, we may need this on INITIAL
if (_file_type == 1 && _interpolate_times)
updateExodusTimeInterpolation();

// Set initialization flag
_initialized = true;
}
Expand Down Expand Up @@ -1061,13 +1064,37 @@ SolutionUserObjectBase::evalMeshFunction(const Point & p,
// Extract a value from the _mesh_function
{
Threads::spin_mutex::scoped_lock lock(_solution_user_object_mutex);

if (func_num == 1)
{
// Check the cache
if (p == _cached_p && (!subdomain_ids || (*subdomain_ids == _cached_subdomain_ids)))
return _cached_values(local_var_index);

// else get a new value
(*_mesh_function)(p, 0.0, output, subdomain_ids);
// and cache it
_cached_p = p;
if (subdomain_ids)
_cached_subdomain_ids = *subdomain_ids;
_cached_values = output;
}

// Extract a value from _mesh_function2
else if (func_num == 2)
(*_mesh_function2)(p, 0.0, output, subdomain_ids);
{
// Check the cache
if (p == _cached_p2 && (!subdomain_ids || (*subdomain_ids == _cached_subdomain_ids2)))
return _cached_values2(local_var_index);

// else get a new value
(*_mesh_function2)(p, 0.0, output, subdomain_ids);
// and cache it
_cached_p2 = p;
if (subdomain_ids)
_cached_subdomain_ids2 = *subdomain_ids;
_cached_values2 = output;
}
else
mooseError("The func_num must be 1 or 2");
}
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
[Mesh]
[gen]
type = GeneratedMeshGenerator
dim = 2
xmin = 0
xmax = 1
ymin = 0
ymax = 1
nx = 4
ny = 2
[]
[]

[Problem]
kernel_coverage_check = false
skip_nl_system_check = true
solve = false
[]

[AuxVariables]
[var1]
family = MONOMIAL
order = CONSTANT
[]
[var2]
family = MONOMIAL
order = CONSTANT
[]
[]

# Auxkernels execute inside an element loop, the solution UO value
# should be cached when called from the first auxkernel, then retrieved by the second one
[AuxKernels]
[var1]
type = SolutionAux
variable = var1
solution = soln
from_variable = var1
execute_on = 'INITIAL'
[]
[var2]
type = SolutionAux
variable = var2
solution = soln
from_variable = var2
execute_on = 'INITIAL'
[]
[]

# We use the same exodus solution file as the other test
[UserObjects]
[soln]
type = SolutionUserObject
mesh = write_exodus_initial_out.e
system_variables = 'var1 var2'
execute_on = 'INITIAL'
# timestep = 1
[]
[]

[Executioner]
type = Transient
num_steps = 2
# Different dt to use interpolation
dt = 0.1
start_time = 0.005
[]

[Outputs]
exodus = true
execute_on = FINAL
[]
29 changes: 25 additions & 4 deletions test/tests/userobjects/solution_user_object/tests
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@
issues = '#7244'
design = 'SolutionUserObject.md'

[./discontinuous_value_solution_uo_p1]
[discontinuous_value_solution_uo_p1]
type = 'Exodiff'
input = 'discontinuous_value_solution_uo_p1.i'
exodiff = 'discontinuous_value_solution_uo_p1.e'

requirement = 'The system shall be capable of writing out a solution file with both continuous and discontinuous fields for the purpose of verifying that ability to read those solutions back into a new simulation.'
[../]
[./discontinuous_value_solution_uo_p2]
[]
[discontinuous_value_solution_uo_p2]
type = 'CSVDiff'
input = 'discontinuous_value_solution_uo_p2.i'
csvdiff = 'discontinuous_value_solution_uo_p2.csv'
prereq = discontinuous_value_solution_uo_p1

requirement = 'The system shall be capable of reading in field information and producing gradient values from both continuous and discontinuous fields.'
[../]
[]
[test_scalar]
type = RunApp
cli_args = 'UserObjects/soln/mesh=gold/testscalarrename.e UserObjects/soln/system_variables=""'
Expand Down Expand Up @@ -54,4 +54,25 @@
issues = "#31238"
requirement = "The system shall be able to read in a variable from a previous exodus file that only has fiels at time 0."
[]

[write_exodus_multiple_vars]
type = RunApp
prereq = 'read_exodus_initial'
input = "write_exodus_initial.i"
# Create more than 1 timestep and more than 1 variable
cli_args = "AuxVariables/var1/initial_condition=2 AuxVariables/var2/initial_condition=1
AuxKernels/v1/type=FunctionAux AuxKernels/v1/variable=var1 AuxKernels/v1/function='2+t'
AuxKernels/v2/type=FunctionAux AuxKernels/v2/variable=var2 AuxKernels/v2/function='1+t'
Executioner/type=Transient Executioner/num_steps=10"
issues = "#31238"
requirement = "The system shall be capable of writing out an exodus file with multiple variables."
[]
[read_exodus_multiple_vars]
type = Exodiff
input = "read_exodus_multiple_vars.i"
exodiff = "read_exodus_multiple_vars_out.e"
prereq = "write_exodus_multiple_vars"
issues = "#31238 #31747 #31767"
requirement = "The system shall be able to read in multiple variables from a previous exodus file, loaded separately from the mesh file, leveraging caching and time step interpolation."
[]
[]