idaholab / moose

Multiphysics Object Oriented Simulation Environment
https://www.mooseframework.org
GNU Lesser General Public License v2.1
1.77k stars 1.05k forks source link

Function evaluation does not work after include #26664

Open jmeier opened 9 months ago

jmeier commented 9 months ago

Bug Description

After using !include the evaluation of an unit conversion (e.g. ${units 20 kN/m^2 -> MN/m^2}) fails.

Steps to Reproduce

Please see the input files given below. Please note, the different values of FakeUser_MassTop1 and FakeUser_MassTop2 when executing with --show-input.

  [./FakeUser_MassTop1]
    _unique_action_name          = AddFunctionActionFunctions/FakeUser_MassTop1
    control_tags                 = 20                                      <---- THIS IS FINE
    inactive                     = (no_default)
    isObjectAction               = 1
    type                         = ParsedFunction
    enable                       = 1
    execute_on                   = LINEAR
    expression                   = a
    symbol_names                 = a
    symbol_values                = 1
    vals                         = INVALID
    value                        = INVALID
    vars                         = INVALID
  [../]

  [./FakeUser_MassTop2]
    _unique_action_name          = AddFunctionActionFunctions/FakeUser_MassTop2
    control_tags                 = '${units 20 kg -> ${modelunit_mass}}'  <---- THIS IS NOT FINE
    inactive                     = (no_default)
    isObjectAction               = 1
    type                         = ParsedFunction
    enable                       = 1
    execute_on                   = LINEAR
    expression                   = a
    symbol_names                 = a
    symbol_values                = 1
    vals                         = INVALID
    value                        = INVALID
    vars                         = INVALID
  [../]

Impact

Sadly, this beaks all my models having an !include.

Example

Please run "file 2" with --show-input:

file 1: "var-include.i"

# blaaa
fooInt = 7
fooDbl = 3.3
fooStr = "blubb bb 6"
fooArr = 'blubb blubb'
modelunit_density = 'kg/m^3'

[Functions]
    [FakeUser_fooInt]
        type = ParsedFunction
        expression = 'a'
        symbol_names = 'a'
        symbol_values = '${fooInt}'
    []

    [FakeUser_fooDbl]
        type = ParsedFunction
        expression = 'a'
        symbol_names = 'a'
        symbol_values = '${fooDbl}'
    []
    [FakeUser_fooStr]
        type = ParsedFunction
        expression = 'a'
        symbol_names = 'a'
        symbol_values = '1'
        control_tags = ${fooStr}
    []
    [FakeUser_fooArr]
        type = ParsedFunction
        expression = 'a'
        symbol_names = 'a'
        symbol_values = '1'
        control_tags = ${fooArr}
    []
    [FakeUser_modelunit_density]
        type = ParsedFunction
        expression = 'a'
        symbol_names = 'a'
        symbol_values = '1'
        control_tags = ${modelunit_density}
    []
[]

file 2:

# primary model units
modelunit_mass = 'kg'
modelunit_pressure = 'kN/m^2'

mass_top1 = ${units 20 kg -> ${modelunit_mass}}

# define some other variables
!include var-include.i

mass_top2 = ${units 20 kg -> ${modelunit_mass}}

#some model-specific variables
material_density = ${units 21.5E3 kg/m^3 -> ${modelunit_density}}
sig_top = ${units 20 kN/m^2 -> ${modelunit_pressure}}

[Functions]
    [FakeUser_MaterialDensity]
        type = ParsedFunction
        expression = 'a'
        symbol_names = 'a'
        symbol_values = '1'
        control_tags = ${material_density}
    []
    [FakeUser_ModelUnitDensity2]
        type = ParsedFunction
        expression = 'a'
        symbol_names = 'a'
        symbol_values = '1'
        control_tags = ${modelunit_density}
    []
    [FakeUser_MassTop1]
        type = ParsedFunction
        expression = 'a'
        symbol_names = 'a'
        symbol_values = '1'
        control_tags = ${mass_top1}
    []
    [FakeUser_MassTop2]
        type = ParsedFunction
        expression = 'a'
        symbol_names = 'a'
        symbol_values = '1'
        control_tags = ${mass_top2}
    []
    [FakeUser_SigTop]
        type = ParsedFunction
        expression = 'a'
        symbol_names = 'a'
        symbol_values = '1'
        control_tags = ${sig_top}
    []
[]

[Mesh]
  type = GeneratedMesh
  dim = 3
  nx = 1
  ny = 1
  nz = 1
  xmin = 0.0
  xmax = 1.0
  ymin = 0.0
  ymax = 1.0
  zmin = 0.0
  zmax = 1.0
  elem_type = TET10
[]

[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  large_kinematics = false
[]

[Modules/TensorMechanics/Master]
  [./all]
    new_system = true
    formulation = total
    strain = small
    add_variables = true
    generate_output = 'stress_xx stress_xy stress_xz stress_yy stress_yz stress_zz '
  []
[]

[Materials]

  [./volAll_elasticity_tensor]
    type = ComputeIsotropicElasticityTensor
    youngs_modulus = ${units 4500 MN/m^2 -> ${modelunit_pressure}}
    poissons_ratio = 0.15
  []

  [./volAll_stress]
    type = ComputeLagrangianWrappedStress
  []

  [./volAll_stress_base]
    type = ComputeLinearElasticStress
  []

[]

[Executioner]
  type = Transient
  end_time = 0.0
[]

[Outputs]
[]

MOOSE used

git log -1 gives:

commit 541c02534c72907166492578147de5dce2b6f172 (HEAD -> master, origin/scheduled, origin/master)
Merge: 5b93c2457e f628af566d
Author: MOOSE maintenance <bounces@inl.gov>
Date:   Thu Jan 18 18:55:15 2024 -0700

Merge commit 'f628af566d2c6de203bb71a5c8eff8614fa9ed0d'
GiudGiud commented 9 months ago

I used VSCode to auto-format this and it added quotes around all the units calls. Then it seems to be parsing fine?

GiudGiud commented 9 months ago
# primary model units
modelunit_mass = 'kg'
modelunit_pressure = 'kN/m^2'

mass_top1 = '${units 20 kg -> ${modelunit_mass}}'

# define some other variables
!include input1.i

mass_top2 = '${units 20 kg -> ${modelunit_mass}}'

#some model-specific variables
material_density = '${units 21.5E3 kg/m^3 -> ${modelunit_density}}'
sig_top = '${units 20 kN/m^2 -> ${modelunit_pressure}}'

[Functions]
  [FakeUser_MaterialDensity]
    type = ParsedFunction
    expression = 'a'
    symbol_names = 'a'
    symbol_values = '1'
    control_tags = ${material_density}
  []
  [FakeUser_ModelUnitDensity2]
    type = ParsedFunction
    expression = 'a'
    symbol_names = 'a'
    symbol_values = '1'
    control_tags = ${modelunit_density}
  []
  [FakeUser_MassTop1]
    type = ParsedFunction
    expression = 'a'
    symbol_names = 'a'
    symbol_values = '1'
    control_tags = ${mass_top1}
  []
  [FakeUser_MassTop2]
    type = ParsedFunction
    expression = 'a'
    symbol_names = 'a'
    symbol_values = '1'
    control_tags = ${mass_top2}
  []
  [FakeUser_SigTop]
    type = ParsedFunction
    expression = 'a'
    symbol_names = 'a'
    symbol_values = '1'
    control_tags = ${sig_top}
  []
[]

[Mesh]
  type = GeneratedMesh
  dim = 3
  nx = 1
  ny = 1
  nz = 1
  xmin = 0.0
  xmax = 1.0
  ymin = 0.0
  ymax = 1.0
  zmin = 0.0
  zmax = 1.0
  elem_type = TET10
[]

[GlobalParams]
  displacements = 'disp_x disp_y disp_z'
  large_kinematics = false
[]

[Modules/TensorMechanics/Master]
  [all]
    new_system = true
    formulation = total
    strain = small
    add_variables = true
    generate_output = 'stress_xx stress_xy stress_xz stress_yy stress_yz stress_zz '
  []
[]

[Materials]

  [volAll_elasticity_tensor]
    type = ComputeIsotropicElasticityTensor
    youngs_modulus = '${units 4500 MN/m^2 -> ${modelunit_pressure}}'
    poissons_ratio = 0.15
  []

  [volAll_stress]
    type = ComputeLagrangianWrappedStress
  []

  [volAll_stress_base]
    type = ComputeLinearElasticStress
  []

[]

[Executioner]
  type = Transient
  end_time = 0.0
[]

[Outputs]
[]
jmeier commented 9 months ago

Dear @GiudGiud,

Unfortunately, no. After copy&paste of your code, the problem remains. If I move the line mass_top2 = '${units 20 kg -> ${modelunit_mass}}' above the !include, it parses correctly. But this is not a solution for the underlying problem (in other models I need to parse variables using the stuff inside the !include).

GiudGiud commented 9 months ago

Thanks for checking. @brandonlangley could you please take a look?

joshuahansel commented 9 months ago

Is this related to https://github.com/idaholab/moose/issues/26164 by chance?

brandonlangley commented 9 months ago

@grunerjmeier @GiudGiud @joshuahansel -

Is this related to #26164 by chance?

Yes, I looked into this and it is that same issue from #26164 which is not actually a problem with !include at all.

You will see that exact same behavior if you replace !include var-include.i with the var-include.i contents.

Effectively !include filename.i just copies and pastes the contents of filename.i into the !include location.

And after this copying and pasting replacement of the content is complete, all of the regular HIT input rules apply.

So your !include var-include.i imports that content and your main input file basically looks like this afterward:

# primary model units
. . .

mass_top1 = ${units 20 kg -> ${modelunit_mass}}

# define some other variables

# blaaa
. . .

[Functions]
    [FakeUser_fooInt]
                . . .
    []
    [FakeUser_fooDbl]
                . . .
    []
    [FakeUser_fooStr]
                . . .
    []
    [FakeUser_fooArr]
                . . .
    []
    [FakeUser_modelunit_density]
                . . .
    []
[]

mass_top2 = ${units 20 kg -> ${modelunit_mass}}

#some model-specific variables
. . .

[Functions]
    [FakeUser_MaterialDensity]
                . . .
    []
    [FakeUser_ModelUnitDensity2]
                . . .
    []
    [FakeUser_MassTop1]
                . . .
        control_tags = ${mass_top1}
    []
    [FakeUser_MassTop2]
                . . .
        control_tags = ${mass_top2}
    []
    [FakeUser_SigTop]
                . . .
    []
[]

[Mesh]
  . . .
[]

[GlobalParams]
  . . .
[]

[Modules/TensorMechanics/Master]
  . . .
[]

[Materials]
  . . .
[]

[Executioner]
  . . .
[]

[Outputs]
[]

Then the next stage walks over the parse tree of that input structure and merges blocks that have the same name.

This stage merges block content upward and since you have two [Functions] blocks, it looks like this afterward:

# primary model units
. . .

mass_top1 = ${units 20 kg -> ${modelunit_mass}}

# define some other variables

# blaaa
. . .

[Functions]
    [FakeUser_fooInt]
                . . .
    []

    [FakeUser_fooDbl]
                . . .
    []
    [FakeUser_fooStr]
                . . .
    []
    [FakeUser_fooArr]
                . . .
    []
    [FakeUser_modelunit_density]
                . . .
    []
    [FakeUser_MaterialDensity]
                . . .
    []
    [FakeUser_ModelUnitDensity2]
                . . .
    []
    [FakeUser_MassTop1]
                . . .
        control_tags = ${mass_top1}
    []
    [FakeUser_MassTop2]
                . . .
        control_tags = ${mass_top2}
    []
    [FakeUser_SigTop]

[]

mass_top2 = ${units 20 kg -> ${modelunit_mass}}

#some model-specific variables
. . .

[Mesh]
  . . .
[]

[GlobalParams]
  . . .
[]

[Modules/TensorMechanics/Master]
  . . .
[]

[Materials]
  . . .
[]

[Executioner]
  . . .
[]

[Outputs]
[]

And Functions/FakeUser_MassTop2/control_tags=${mass_top2} is above mass_top2=${...${modelunit_mass}}.

Next, all the brace expressions (${...}) are evaluated according to the logic noted in this wiki page about order:

Here are some important details about how brace-expressions are evaluated:

  • Brace expressions are evaluated in input-file order (i.e. lexical order) from top to bottom of the input file. Brace expressions must not depend on field values using brace expressions that occur later in the input file - although they can depend on field values without brace expressions that occur later in the input file.

So replacing the !include with the var-include.i content for multiple [Functions] blocks will also cause this.

As this comment in #26164 mentioned, changing this consistently would involve a brace substitution logic update.

joshuahansel commented 9 months ago

Thanks @brandonlangley. I think this issue will keep coming up. Are you able to work on a fix for this in the near future?

joshuahansel commented 9 months ago

@brandonlangley I'm sorry for pestering, but are you able to help with this in the near future? If you're pretty tightly booked up, that's ok, but I think we should find someone for this somewhat soon.

brandonlangley commented 9 months ago

@joshuahansel -

If you add it to this project, I can ask Thursday in my standup about my priority and get a better idea of when I could do it.

https://github.com/orgs/idaholab/projects/10

Or if you feel like this is actually a duplicate to #26164, then maybe this issue could be closed as a duplicate to that issue?

joshuahansel commented 9 months ago

@brandonlangley Thanks! I went ahead and added both issues. I'm pretty sure they're the same, but let's just keep both since we're not 100% and then we can close each after we verify the fix to the respective examples.

brandonlangley commented 9 months ago

@joshuahansel -

I brought this up today during my standup related to the NEAMS '24 LSP and Frontend Improvements project.

And @dschwen is actually already planning to rework the brace expression expansion system sometime soon.

This will include not having a static evaluation order for the different ${fparse...}, ${units...}, etc. types.

His rework will also involve changes related to the evaluation order here and #26164 so I'm leaving this to him.

You can remove this and #26164 from that LSP focused NEAMS '24 LSP and Frontend Improvements project.

joshuahansel commented 9 months ago

Great, thank you for bringing it up - I'll pester @dschwen from now on then (after an appropriate cooldown) 😄

I removed the issues from that project.