From 4f6b26436ec1df94726020efc5bca4b5fa9e2a0a Mon Sep 17 00:00:00 2001 From: JKRT Date: Thu, 18 Jun 2026 18:43:58 +0200 Subject: [PATCH 1/5] CI(docs): drop test-only submodule before Pkg.develop in docs job The docs job runs `Pkg.develop(path = OMFrontend.jl)`, which makes Pkg inspect the package git tree. The `test/3rdParty/Buildings` submodule is checked out with submodules:false and is not needed for documentation, but its dangling reference makes LibGit2 fail with "cannot get submodules without a working tree". Remove the reference so develop sees a clean tree. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/Documenter.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/Documenter.yml b/.github/workflows/Documenter.yml index dca1137..23c8362 100644 --- a/.github/workflows/Documenter.yml +++ b/.github/workflows/Documenter.yml @@ -31,6 +31,17 @@ jobs: with: path: OMFrontend.jl + # The docs step does `Pkg.develop(path = OMFrontend.jl)`, which makes Pkg + # inspect the package git tree. The test-only `test/3rdParty/Buildings` + # submodule is not fetched (submodules: false) and is not needed for docs, + # but its presence makes LibGit2 fail with "cannot get submodules without + # a working tree". Drop the reference so develop operates on a clean tree. + - name: Drop test-only submodule (not needed for docs) + shell: bash + run: | + rm -f OMFrontend.jl/.gitmodules + rm -rf OMFrontend.jl/test/3rdParty/Buildings + # OMFrontend.jl/Project.toml uses [sources] to point at sibling working # copies. We mirror the CI workflow and lay the siblings out alongside the # main checkout. From 8ede7c0bad51217baa88ec88c4273f86f8a80899 Mon Sep 17 00:00:00 2001 From: JKRT Date: Thu, 18 Jun 2026 18:49:40 +0200 Subject: [PATCH 2/5] CI: only collect and upload coverage on the ubuntu runner Coverage is redundant across OSes. Gate --code-coverage, processcoverage, and the Codecov upload behind a matrix `coverage` flag set only on ubuntu-latest, so Windows and macOS run tests without the coverage overhead. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 121a194..c19a416 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,9 +34,11 @@ jobs: matrix: # Listing every combination explicitly keeps the matrix predictable. include: + # Coverage is only collected/uploaded on one runner. - os: ubuntu-latest arch: x64 version: '1.12' + coverage: true - os: windows-latest arch: x64 version: '1.12' @@ -180,19 +182,22 @@ jobs: # most expensive part of the build. Test is already in [deps] so # no [extras] merging is needed. # --code-coverage=user emits .cov files next to user source for the - # downstream julia-processcoverage step. + # downstream julia-processcoverage step. Only enabled on the coverage + # runner; the others run tests without the coverage overhead. shell: bash working-directory: OMFrontend.jl run: | - julia --color=yes --code-coverage=user --project=. -e ' + julia --color=yes ${{ matrix.coverage && '--code-coverage=user' || '' }} --project=. -e ' include("test/runtests.jl") ' - uses: julia-actions/julia-processcoverage@v1 + if: matrix.coverage with: directories: OMFrontend.jl/src - name: Upload coverage to Codecov + if: matrix.coverage uses: codecov/codecov-action@v4 with: files: lcov.info From f4f009d1e69155c01f8a18bc455848db37af73c1 Mon Sep 17 00:00:00 2001 From: JKRT Date: Thu, 18 Jun 2026 19:04:42 +0200 Subject: [PATCH 3/5] CI(docs): develop OMFrontend with siblings in one resolve Developing the siblings first re-resolved the docs environment while OMFrontend was still a registry/git dependency, so Pkg cloned OMFrontend (and OMParser/ImmutableList) from GitHub and failed on the test submodule. Develop OMFrontend in the same call so it is never materialized from git. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/Documenter.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Documenter.yml b/.github/workflows/Documenter.yml index 23c8362..da69e61 100644 --- a/.github/workflows/Documenter.yml +++ b/.github/workflows/Documenter.yml @@ -143,8 +143,13 @@ jobs: "../OMRuntimeExternalC.jl", "../SCode.jl", ] - Pkg.develop([Pkg.PackageSpec(path = p) for p in siblings]) - Pkg.develop(Pkg.PackageSpec(path = pwd())) + # Develop OMFrontend together with the siblings in a single call. + # Developing the siblings first re-resolves the docs environment + # while OMFrontend is still a registry/git dependency, which makes + # Pkg clone it from GitHub and fail on its test submodule. + specs = [Pkg.PackageSpec(path = p) for p in siblings] + push!(specs, Pkg.PackageSpec(path = pwd())) + Pkg.develop(specs) Pkg.instantiate() ' From ea88bbb0ab96b93e4abf15d4f1dacc90308d2067 Mon Sep 17 00:00:00 2001 From: JKRT Date: Sun, 21 Jun 2026 12:54:48 +0200 Subject: [PATCH 4/5] JSON export done. Separate flattening via Flag expanded structural construction. --- Project.toml | 2 +- src/Export/StructuralModeJSON.jl | 137 ++++++++++++++++++++++-- src/NewFrontend/NFFlatten.jl | 29 +++-- src/NewFrontend/NFLookup.jl | 8 ++ src/OMFrontend.jl | 117 +++++++++++++------- src/Util/Flags.jl | 7 ++ src/Util/FlagsUtil.jl | 2 +- test/Models/CoupledPenduliNormal.mo | 38 +++++++ test/Models/CoupledPenduliStructural.mo | 38 +++++++ test/jsonExportTests.jl | 121 +++++++++++++++++++++ test/replaceableTests.jl | 17 ++- test/runtests.jl | 8 ++ test/separateFlattenTests.jl | 34 ++++++ 13 files changed, 494 insertions(+), 64 deletions(-) create mode 100644 test/Models/CoupledPenduliNormal.mo create mode 100644 test/Models/CoupledPenduliStructural.mo create mode 100644 test/jsonExportTests.jl create mode 100644 test/separateFlattenTests.jl diff --git a/Project.toml b/Project.toml index 93a92a5..8275d96 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "OMFrontend" uuid = "b10394b5-f439-4073-a0c5-e09cb00cf46c" authors = ["John Tinnerholm ", "Martin Sjölund ", "Adrian Pop "] -version = "1.1.0" +version = "1.1.1" [deps] Absyn = "ce2f92e2-a952-11e9-0543-8b443f216f1d" diff --git a/src/Export/StructuralModeJSON.jl b/src/Export/StructuralModeJSON.jl index c1ad547..fb16a7c 100644 --- a/src/Export/StructuralModeJSON.jl +++ b/src/Export/StructuralModeJSON.jl @@ -631,9 +631,126 @@ end # === Public API === +#= Canonical OCaml ATD schema for the exported JSON. Single source of truth; + docs/structural_mode_json.atd is generated from this. =# +const ATD_SCHEMA = """ +(* ATD type definitions for flat Modelica model JSON export. + These types define the schema for both the hierarchy and flat model JSON + produced by `OMFrontend.exportJSON`. *) + +(* -- Shared types -- *) + +type variability = [ + | Parameter + | Continuous +] + +type visibility = [ + | Public + | Protected +] + +type variable = { + name: string; + type_name : string; + variability: variability; + visibility: visibility; + highest_differentiation_order: int; + ?default_value : string option; + ?attributes: string option; +} + +type equation = { + id: string; + equation: string; + differentiation_order: int; + variables_used: string list; +} + +(* -- Hierarchy JSON -- *) + +type structural_class_summary = { + name: string; + highest_differentiation_order: int; + highest_differentiation_order_variables: string list; +} + +type structural_component = { + name: string; + type_name : string; + n_variables: int; + n_parameters: int; + n_equations: int; +} + +type hierarchy = { + model: string; + structural_classes: structural_class_summary list; + structural_components: structural_component list; + coupling_equations: string list; + ~top_level_variables: string list; +} + +(* -- Flat model JSON -- *) + +type structural_class = { + name: string; + highest_differentiation_order: int; + highest_differentiation_order_variables: string list; + variables: variable list; + equations: equation list; +} + +type parameter_override = { + parameter: string; + value: string; +} + +type component = { + name: string; + class_name : string; + ~parameter_overrides: parameter_override list; +} + +type top_level_section = { + ~variables: variable list; + ~equations: equation list; +} + +type var_equation_mapping = { + variable: string; + equation_ids: string list; +} + +type flat_model = { + model: string; + structural_classes: structural_class list; + components: component list; + top_level: top_level_section; + variable_to_equations: var_equation_mapping list; +} """ - exportFlatModelJSON(FM; output_dir=".", base_name, hierarchy=true, flat=true, - class_mapping=nothing) -> NamedTuple + +""" + exportATD(; output_dir=".", base_name="structural_mode_json") -> String + +Write the canonical OCaml ATD schema (`ATD_SCHEMA`) for the exported JSON to +`/.atd` and return the written path. The schema is +model-independent. +""" +function exportATD(; output_dir::AbstractString = ".", + base_name::AbstractString = "structural_mode_json") + mkpath(output_dir) + path = joinpath(output_dir, base_name * ".atd") + open(path, "w") do io + write(io, ATD_SCHEMA) + end + return path +end + +""" + exportJSON(FM; output_dir=".", base_name, hierarchy=true, flat=true, + class_mapping=nothing, atd=false) -> NamedTuple Walk a FlatModel and write `_hierarchy.json` and/or `_flat.json`. Structural-mode components (in `FM.structuralSubmodels`) are deduplicated into @@ -643,15 +760,17 @@ class templates with per-instance parameter overrides. to class name (e.g. `Dict("p1" => "Pendulum")`). When not provided, the class name defaults to the uppercase-first form of the first instance in each fingerprint group. -Returns a `NamedTuple{(:hierarchy_path, :flat_path)}`. Either entry is the -written file path, or `nothing` when the corresponding keyword was `false`. +Returns a `NamedTuple{(:hierarchy_path, :flat_path, :atd_path)}`. Each entry is the +written file path, or `nothing` when the corresponding keyword was `false`. Pass +`atd=true` to also write `.atd` (the schema in `ATD_SCHEMA`). """ -function exportFlatModelJSON(fmOrTuple; +function exportJSON(fmOrTuple; output_dir::AbstractString = ".", base_name::AbstractString = "", hierarchy::Bool = true, flat::Bool = true, - class_mapping::Union{Dict{String,String}, Nothing} = nothing) + class_mapping::Union{Dict{String,String}, Nothing} = nothing, + atd::Bool = false) fm = fmOrTuple isa Frontend.FLAT_MODEL ? fmOrTuple : first(fmOrTuple) isempty(base_name) && (base_name = fm.name) mkpath(output_dir) @@ -659,6 +778,7 @@ function exportFlatModelJSON(fmOrTuple; mapping = _buildClassMapping(submodels, class_mapping) hierPath = nothing flatPath = nothing + atdPath = nothing if hierarchy h = _buildHierarchy(fm, submodels, mapping) hierPath = joinpath(output_dir, base_name * "_hierarchy.json") @@ -673,7 +793,10 @@ function exportFlatModelJSON(fmOrTuple; JSON.print(io, _toDict(f), 2) end end - return (hierarchy_path = hierPath, flat_path = flatPath) + if atd + atdPath = exportATD(output_dir = output_dir, base_name = base_name) + end + return (hierarchy_path = hierPath, flat_path = flatPath, atd_path = atdPath) end end # module StructuralModeJSON diff --git a/src/NewFrontend/NFFlatten.jl b/src/NewFrontend/NFFlatten.jl index 6f81082..0c9fb64 100644 --- a/src/NewFrontend/NFFlatten.jl +++ b/src/NewFrontend/NFFlatten.jl @@ -64,7 +64,7 @@ const NFFunctionTree = FunctionTreeImpl import .FunctionTree -function flatten(classInst::InstNode, name::String; prefix = COMPONENT_REF_EMPTY()) +function flatten(classInst::InstNode, name::String; prefix = COMPONENT_REF_EMPTY(), isTopLevel::Bool = true) local flatModel::FlatModel local sections::Sections local vars::Vector{Variable} @@ -85,6 +85,7 @@ function flatten(classInst::InstNode, name::String; prefix = COMPONENT_REF_EMPTY Variable[], sections, structuralSubmodels, + isTopLevel = isTopLevel, ) flatModel = begin @match sections begin @@ -148,6 +149,8 @@ function flattenClass( #= Extension. Models that are a structural part of a flat model and should not be merged.=# structuralSubModels::List{FLAT_MODEL}, #= End extension =# + ; + isTopLevel::Bool = false, ) #@info "CALLING flattenClass" local comps::Vector{InstNode} @@ -178,7 +181,8 @@ function flattenClass( SOME(listHead(bindings)), vars, sections, - structuralSubModels + structuralSubModels, + isTopLevel = isTopLevel, ) bindings = listRest(bindings) end @@ -187,7 +191,8 @@ function flattenClass( #@info "Calling flatten component" toString(c) (vars, sections, structuralSubModels) = flattenComponent(c, prefix, visibility, binding, - vars, sections, structuralSubModels) + vars, sections, structuralSubModels, + isTopLevel = isTopLevel) end end else @@ -195,7 +200,8 @@ function flattenClass( #@info "Calling flatten component" toString(c) (vars, sections, structuralSubModels) = flattenComponent(c, prefix, visibility, NONE(), - vars, sections, structuralSubModels) + vars, sections, structuralSubModels, + isTopLevel = isTopLevel) end end sections = flattenSections(cls.sections, prefix, sections) @@ -210,7 +216,8 @@ function flattenClass( binding, vars, sections, - structuralSubModels + structuralSubModels, + isTopLevel = isTopLevel, ) () end @@ -243,7 +250,8 @@ function flattenComponent( vars::Vector{Variable}, sections::Sections, #= Passed from the top level class. =# - structuralSubModels::List{FLAT_MODEL} + structuralSubModels::List{FLAT_MODEL}; + isTopLevel::Bool = false, ) #@info "FLATTEN COMPONENT: " * toString(inComponent) local comp_node::InstNode @@ -273,7 +281,12 @@ function flattenComponent( end if isComplexComponent(ty) #= A complex component such as a model or a class =# - if c.attributes.isStructuralMode == true + #= Keep the component as a separate submodel when it is declared + `structuralmode`, or when the separate-index-reduction flag splits + every top-level component. The flag is gated on isTopLevel so it + does not cascade into a submodel's own internals. =# + if c.attributes.isStructuralMode == true || + (isTopLevel && Flags.isSet(Flags.NF_SEPARATE_INDEX_REDUCTION)) #@debug "FLATTEN A COMPLEX STRUCTURAL COMPONENT" #= Since this component is structural we do not flatten it. @@ -284,7 +297,7 @@ function flattenComponent( local prefixOfComponent = fromNode(comp_node, ty) structuralSubModels = flatten(comp_node #= TODO: Or do we need some instantation specific stuff=#, - name(comp_node), prefix = prefixOfComponent) <| structuralSubModels + name(comp_node), prefix = prefixOfComponent, isTopLevel = false) <| structuralSubModels else (vars, sections) = flattenComplexComponent( comp_node, diff --git a/src/NewFrontend/NFLookup.jl b/src/NewFrontend/NFLookup.jl index 0574366..1ba0c6b 100644 --- a/src/NewFrontend/NFLookup.jl +++ b/src/NewFrontend/NFLookup.jl @@ -816,6 +816,14 @@ function lookupCrefInNode(cref::Absyn.ComponentRef #=modification-040321=#, end end end + #= Reject name lookup inside a still-partial class/package (OMC parity: + "%s is partial, name lookup is not allowed in partial classes"). A + redeclared package resolves to its concrete target here, so this only + fires for a genuinely-unredeclared partial default. =# + if node isa CLASS_NODE && isPartial(scope) + Error.addSourceMessageAndFail( + Error.LOOKUP_IN_PARTIAL_CLASS, list(scopeName(scope)), sourceInfo()) + end name = AbsynUtil.crefFirstIdent(cref) cls = getClass(scope) @match ENTRY_INFO(n, is_import) = lookupElement(name, cls) diff --git a/src/OMFrontend.jl b/src/OMFrontend.jl index a1ac76d..32b7ebc 100644 --- a/src/OMFrontend.jl +++ b/src/OMFrontend.jl @@ -142,12 +142,14 @@ end ..... """ function instantiateSCodeToFM(elementToInstantiate::String, - inProgram::SCode.Program; scalarize = true) + inProgram::SCode.Program; scalarize = true, + separateIndexReduction = false) # initialize globals Frontend.Global.initialize() # make sure we have all the flags loaded! # Frontend.Flags.new(Flags.emptyFlags) Frontend.FlagsUtil.set(Frontend.Flags.NF_SCALARIZE, scalarize) + Frontend.FlagsUtil.set(Frontend.Flags.NF_SEPARATE_INDEX_REDUCTION, separateIndexReduction) local builtinSCode = NFModelicaBuiltinCache["NFModelicaBuiltin"] local program = listReverse(listAppend(builtinSCode, inProgram)) local path = Frontend.AbsynUtil.stringPath(elementToInstantiate) @@ -364,10 +366,12 @@ end Returns the flat representation of a modelica model along with the functions used and define by the model. """ -function flattenModel(modelName::String, fileName::String; scalarize = true) +function flattenModel(modelName::String, fileName::String; scalarize = true, + separateIndexReduction = false) local absynProgram = parseFile(fileName) local sCodeProgram = translateToSCode(absynProgram) - (FM, cache) = instantiateSCodeToFM(modelName, sCodeProgram; scalarize = scalarize) + (FM, cache) = instantiateSCodeToFM(modelName, sCodeProgram; scalarize = scalarize, + separateIndexReduction = separateIndexReduction) end """ @@ -1009,6 +1013,7 @@ function flattenModelWithLibraries(modelName::String, MSL::Bool = false, MSL_Version::String = "MSL:3.2.3", scalarize::Bool = true, + separateIndexReduction::Bool = false, forceReload::Bool = false) local combined = if isempty(fileName) nil @@ -1030,7 +1035,8 @@ function flattenModelWithLibraries(modelName::String, end combined = listAppend(combined, LIBRARY_CACHE[mslKey]) end - (FM, cache) = instantiateSCodeToFM(modelName, combined; scalarize = scalarize) + (FM, cache) = instantiateSCodeToFM(modelName, combined; scalarize = scalarize, + separateIndexReduction = separateIndexReduction) end @@ -1060,6 +1066,31 @@ function disableDumpDebug() @info "Disabled Flags.NF_DUMP_FLAT. Old status was $(status)" end +""" +``` +enableSeparateIndexReduction() +``` +Flatten each top-level component into its own structural submodel +(`FLAT_MODEL.structuralSubmodels`) so the backend can run index reduction +separately per component. Equivalent to passing `separateIndexReduction = true` +to `flattenModel`/`instantiateSCodeToFM`. Disable with `disableSeparateIndexReduction()`. +""" +function enableSeparateIndexReduction() + status = FlagsUtil.enableDebug(Flags.NF_SEPARATE_INDEX_REDUCTION) + @info "Enabled Flags.NF_SEPARATE_INDEX_REDUCTION. Old status was $(status)" +end + +""" +``` +disableSeparateIndexReduction() +``` +Restore the default whole-model flattening (top-level components are inlined). +""" +function disableSeparateIndexReduction() + status = FlagsUtil.disableDebug(Flags.NF_SEPARATE_INDEX_REDUCTION) + @info "Disabled Flags.NF_SEPARATE_INDEX_REDUCTION. Old status was $(status)" +end + Base.show(io::IO, ::MIME"text/plain", fm::OMFrontend.Frontend.FLAT_MODEL) = begin print(io, "Flat Model:\n", string(fm)) end @@ -1145,35 +1176,37 @@ include("cli.jl") include("precompilation.jl") """ - exportFlatModelJSON(FM; output_dir=".", base_name, hierarchy=true, flat=true, - class_mapping=nothing) + exportJSON(FM; output_dir=".", base_name, hierarchy=true, flat=true, + class_mapping=nothing) -Export a flat model as `_hierarchy.json` and/or `_flat.json` in +Export an already-flattened model `FM` (a `FLAT_MODEL` or the `(fm, funcs)` tuple +from `flattenModel`) as `_hierarchy.json` and/or `_flat.json` in `output_dir`. Structural-mode components are grouped into class templates with -parameter overrides. See `StructuralModeJSON.exportFlatModelJSON`. -""" -exportFlatModelJSON(args...; kwargs...) = - StructuralModeJSON.exportFlatModelJSON(args...; kwargs...) - -""" - exportFlatModelJSONFromFile(modelName, fileName, library = ""; - output_dir, base_name, - hierarchy=true, flat=true, class_mapping=nothing) - -Parse `fileName`, instantiate `modelName` to a FlatModel, then call -`exportFlatModelJSON`. When `library` is non-empty, it is loaded via -`loadInstalledLibrary` and combined with the model via `flattenModelWithLibraries` -(e.g. `library = "Modelica"`). When `library` is empty, the model is flattened -on its own with `flattenModel`. -""" -function exportFlatModelJSONFromFile(modelName::AbstractString, - fileName::AbstractString, - library::AbstractString = ""; - output_dir::AbstractString = ".", - base_name::AbstractString = "", - hierarchy::Bool = true, - flat::Bool = true, - class_mapping::Union{Dict{String,String}, Nothing} = nothing) +parameter overrides. See `StructuralModeJSON.exportJSON`. +""" +exportJSON(fmOrTuple; kwargs...) = + StructuralModeJSON.exportJSON(fmOrTuple; kwargs...) + +""" + exportJSON(modelName, fileName, library = ""; + output_dir, base_name, + hierarchy=true, flat=true, class_mapping=nothing, atd=false) + +Parse `fileName`, instantiate `modelName` to a FlatModel, then export it as JSON. +When `library` is non-empty, it is loaded via `loadInstalledLibrary` and combined +with the model via `flattenModelWithLibraries` (e.g. `library = "Modelica"`). When +`library` is empty, the model is flattened on its own with `flattenModel`. Pass +`atd=true` to also write the `.atd` schema. +""" +function exportJSON(modelName::AbstractString, + fileName::AbstractString, + library::AbstractString = ""; + output_dir::AbstractString = ".", + base_name::AbstractString = "", + hierarchy::Bool = true, + flat::Bool = true, + class_mapping::Union{Dict{String,String}, Nothing} = nothing, + atd::Bool = false) (fm, _funcs) = if isempty(library) flattenModel(String(modelName), String(fileName)) else @@ -1181,12 +1214,22 @@ function exportFlatModelJSONFromFile(modelName::AbstractString, flattenModelWithLibraries(String(modelName), String(fileName); libraries = [cacheKey]) end - return StructuralModeJSON.exportFlatModelJSON(fm; - output_dir = output_dir, - base_name = base_name, - hierarchy = hierarchy, - flat = flat, - class_mapping = class_mapping) + return StructuralModeJSON.exportJSON(fm; + output_dir = output_dir, + base_name = base_name, + hierarchy = hierarchy, + flat = flat, + class_mapping = class_mapping, + atd = atd) end +""" + exportATD(; output_dir=".", base_name="structural_mode_json") + +Write the canonical OCaml ATD schema for the exported JSON to +`/.atd` and return the path. The schema is +model-independent. See `StructuralModeJSON.exportATD`. +""" +exportATD(; kwargs...) = StructuralModeJSON.exportATD(; kwargs...) + end #OMFrontend diff --git a/src/Util/Flags.jl b/src/Util/Flags.jl index 24447c0..d2a1e48 100644 --- a/src/Util/Flags.jl +++ b/src/Util/Flags.jl @@ -1446,6 +1446,13 @@ const NF_PARALLEL = false, Gettext.gettext("Opt-in parallelism for OMFrontend phases beyond Absyn-to-SCode (e.g. future parallel instantiation). The Absyn-to-SCode parallel branch is proven safe and runs unconditionally based on `Threads.nthreads()`; this flag does not control it. Reserved for opt-in branches whose correctness is not yet proven. Default off."), )::DebugFlag +const NF_SEPARATE_INDEX_REDUCTION = + DEBUG_FLAG( + 186, + "nfSeparateIndexReduction", + false, + Gettext.gettext("Flatten each top-level component into its own structural submodel so index reduction can run separately per component. Default off."), + )::DebugFlag #= Runtime-toggleable complexity gate for the user-`Inline=true` path. Skips inlining when the body (or worst-case post-substitution form) exceeds the tunable thresholds in `NFInline`. Default on. Flip via diff --git a/src/Util/FlagsUtil.jl b/src/Util/FlagsUtil.jl index ca1c157..53f0c3a 100644 --- a/src/Util/FlagsUtil.jl +++ b/src/Util/FlagsUtil.jl @@ -62,7 +62,7 @@ import ..Gettext #= indices). =# -const allDebugFlags = list(Flags.FAILTRACE, Flags.CEVAL, Flags.CHECK_BACKEND_DAE, Flags.PARMODAUTO, Flags.PTHREADS, Flags.EVENTS, Flags.DUMP_INLINE_SOLVER, Flags.EVAL_FUNC, Flags.GEN, Flags.DYN_LOAD, Flags.GENERATE_CODE_CHEAT, Flags.CGRAPH_GRAPHVIZ_FILE, Flags.CGRAPH_GRAPHVIZ_SHOW, Flags.GC_PROF, Flags.CHECK_DAE_CREF_TYPE, Flags.CHECK_ASUB, Flags.INSTANCE, Flags.CACHE, Flags.RML, Flags.TAIL, Flags.LOOKUP, Flags.PATTERNM_SKIP_FILTER_UNUSED_AS_BINDINGS, Flags.PATTERNM_ALL_INFO, Flags.PATTERNM_DCE, Flags.PATTERNM_MOVE_LAST_EXP, Flags.EXPERIMENTAL_REDUCTIONS, Flags.EVAL_PARAM, Flags.TYPES, Flags.SHOW_STATEMENT, Flags.DUMP, Flags.DUMP_GRAPHVIZ, Flags.EXEC_STAT, Flags.TRANSFORMS_BEFORE_DUMP, Flags.DAE_DUMP_GRAPHV, Flags.INTERACTIVE_TCP, Flags.INTERACTIVE_CORBA, Flags.INTERACTIVE_DUMP, Flags.RELIDX, Flags.DUMP_REPL, Flags.DUMP_FP_REPL, Flags.DUMP_PARAM_REPL, Flags.DUMP_PP_REPL, Flags.DUMP_EA_REPL, Flags.DEBUG_ALIAS, Flags.TEARING_DUMP, Flags.JAC_DUMP, Flags.JAC_DUMP2, Flags.JAC_DUMP_EQN, Flags.JAC_WARNINGS, Flags.DUMP_SPARSE, Flags.DUMP_SPARSE_VERBOSE, Flags.BLT_DUMP, Flags.DUMMY_SELECT, Flags.DUMP_DAE_LOW, Flags.DUMP_INDX_DAE, Flags.OPT_DAE_DUMP, Flags.EXEC_HASH, Flags.PARAM_DLOW_DUMP, Flags.DUMP_ENCAPSULATECONDITIONS, Flags.SHORT_OUTPUT, Flags.COUNT_OPERATIONS, Flags.CGRAPH, Flags.UPDMOD, Flags.STATIC, Flags.TPL_PERF_TIMES, Flags.CHECK_SIMPLIFY, Flags.SCODE_INST, Flags.WRITE_TO_BUFFER, Flags.DUMP_BACKENDDAE_INFO, Flags.GEN_DEBUG_SYMBOLS, Flags.DUMP_STATESELECTION_INFO, Flags.DUMP_EQNINORDER, Flags.SEMILINEAR, Flags.UNCERTAINTIES, Flags.SHOW_START_ORIGIN, Flags.DUMP_SIMCODE, Flags.DUMP_INITIAL_SYSTEM, Flags.GRAPH_INST, Flags.GRAPH_INST_RUN_DEP, Flags.GRAPH_INST_GEN_GRAPH, Flags.GRAPH_INST_SHOW_GRAPH, Flags.DUMP_CONST_REPL, Flags.SHOW_EQUATION_SOURCE, Flags.LS_ANALYTIC_JACOBIAN, Flags.NLS_ANALYTIC_JACOBIAN, Flags.INLINE_SOLVER, Flags.HPCOM, Flags.INITIALIZATION, Flags.INLINE_FUNCTIONS, Flags.DUMP_SCC_GRAPHML, Flags.TEARING_DUMPVERBOSE, Flags.DISABLE_SINGLE_FLOW_EQ, Flags.DUMP_DISCRETEVARS_INFO, Flags.ADDITIONAL_GRAPHVIZ_DUMP, Flags.INFO_XML_OPERATIONS, Flags.HPCOM_DUMP, Flags.RESOLVE_LOOPS_DUMP, Flags.DISABLE_WINDOWS_PATH_CHECK_WARNING, Flags.DISABLE_RECORD_CONSTRUCTOR_OUTPUT, Flags.IMPL_ODE, Flags.EVAL_FUNC_DUMP, Flags.PRINT_STRUCTURAL, Flags.ITERATION_VARS, Flags.ALLOW_RECORD_TOO_MANY_FIELDS, Flags.HPCOM_MEMORY_OPT, Flags.DUMP_SYNCHRONOUS, Flags.STRIP_PREFIX, Flags.DO_SCODE_DEP, Flags.SHOW_INST_CACHE_INFO, Flags.DUMP_UNIT, Flags.DUMP_EQ_UNIT, Flags.DUMP_EQ_UNIT_STRUCT, Flags.SHOW_DAE_GENERATION, Flags.RESHUFFLE_POST, Flags.SHOW_EXPANDABLE_INFO, Flags.DUMP_HOMOTOPY, Flags.OMC_RELOCATABLE_FUNCTIONS, Flags.GRAPHML, Flags.USEMPI, Flags.DUMP_CSE, Flags.DUMP_CSE_VERBOSE, Flags.NO_START_CALC, Flags.CONSTJAC, Flags.VISUAL_XML, Flags.VECTORIZE, Flags.CHECK_EXT_LIBS, Flags.RUNTIME_STATIC_LINKING, Flags.SORT_EQNS_AND_VARS, Flags.DUMP_SIMPLIFY_LOOPS, Flags.DUMP_RTEARING, Flags.DIS_SYMJAC_FMI20, Flags.EVAL_OUTPUT_ONLY, Flags.HARDCODED_START_VALUES, Flags.DUMP_FUNCTIONS, Flags.DEBUG_DIFFERENTIATION, Flags.DEBUG_DIFFERENTIATION_VERBOSE, Flags.FMU_EXPERIMENTAL, Flags.DUMP_DGESV, Flags.MULTIRATE_PARTITION, Flags.DUMP_EXCLUDED_EXP, Flags.DEBUG_ALGLOOP_JACOBIAN, Flags.DISABLE_JACSCC, Flags.FORCE_NLS_ANALYTIC_JACOBIAN, Flags.DUMP_LOOPS, Flags.DUMP_LOOPS_VERBOSE, Flags.SKIP_INPUT_OUTPUT_SYNTACTIC_SUGAR, Flags.OMC_RECORD_ALLOC_WORDS, Flags.TOTAL_TEARING_DUMP, Flags.TOTAL_TEARING_DUMPVERBOSE, Flags.PARALLEL_CODEGEN, Flags.SERIALIZED_SIZE, Flags.BACKEND_KEEP_ENV_GRAPH, Flags.DUMPBACKENDINLINE, Flags.DUMPBACKENDINLINE_VERBOSE, Flags.BLT_MATRIX_DUMP, Flags.LIST_REVERSE_WRONG_ORDER, Flags.PARTITION_INITIALIZATION, Flags.EVAL_PARAM_DUMP, Flags.NF_UNITCHECK, Flags.DISABLE_COLORING, Flags.MERGE_ALGORITHM_SECTIONS, Flags.WARN_NO_NOMINAL, Flags.REDUCE_DAE, Flags.IGNORE_CYCLES, Flags.ALIAS_CONFLICTS, Flags.SUSAN_MATCHCONTINUE_DEBUG, Flags.OLD_FE_UNITCHECK, Flags.EXEC_STAT_EXTRA_GC, Flags.DEBUG_DAEMODE, Flags.NF_SCALARIZE, Flags.NF_EVAL_CONST_ARG_FUNCS, Flags.NF_EXPAND_OPERATIONS, Flags.NF_API, Flags.NF_API_DYNAMIC_SELECT, Flags.NF_API_NOISE, Flags.FMI20_DEPENDENCIES, Flags.WARNING_MINMAX_ATTRIBUTES, Flags.NF_EXPAND_FUNC_ARGS, Flags.DUMP_JL, Flags.DUMP_ASSC, Flags.SPLIT_CONSTANT_PARTS_SYMJAC, Flags.NF_DUMP_FLAT, Flags.DUMP_FORCE_FMI_ATTRIBUTES, Flags.DUMP_FORCE_FMI_INTERNAL_VARIABLES, Flags.NF_PARALLEL)::List +const allDebugFlags = list(Flags.FAILTRACE, Flags.CEVAL, Flags.CHECK_BACKEND_DAE, Flags.PARMODAUTO, Flags.PTHREADS, Flags.EVENTS, Flags.DUMP_INLINE_SOLVER, Flags.EVAL_FUNC, Flags.GEN, Flags.DYN_LOAD, Flags.GENERATE_CODE_CHEAT, Flags.CGRAPH_GRAPHVIZ_FILE, Flags.CGRAPH_GRAPHVIZ_SHOW, Flags.GC_PROF, Flags.CHECK_DAE_CREF_TYPE, Flags.CHECK_ASUB, Flags.INSTANCE, Flags.CACHE, Flags.RML, Flags.TAIL, Flags.LOOKUP, Flags.PATTERNM_SKIP_FILTER_UNUSED_AS_BINDINGS, Flags.PATTERNM_ALL_INFO, Flags.PATTERNM_DCE, Flags.PATTERNM_MOVE_LAST_EXP, Flags.EXPERIMENTAL_REDUCTIONS, Flags.EVAL_PARAM, Flags.TYPES, Flags.SHOW_STATEMENT, Flags.DUMP, Flags.DUMP_GRAPHVIZ, Flags.EXEC_STAT, Flags.TRANSFORMS_BEFORE_DUMP, Flags.DAE_DUMP_GRAPHV, Flags.INTERACTIVE_TCP, Flags.INTERACTIVE_CORBA, Flags.INTERACTIVE_DUMP, Flags.RELIDX, Flags.DUMP_REPL, Flags.DUMP_FP_REPL, Flags.DUMP_PARAM_REPL, Flags.DUMP_PP_REPL, Flags.DUMP_EA_REPL, Flags.DEBUG_ALIAS, Flags.TEARING_DUMP, Flags.JAC_DUMP, Flags.JAC_DUMP2, Flags.JAC_DUMP_EQN, Flags.JAC_WARNINGS, Flags.DUMP_SPARSE, Flags.DUMP_SPARSE_VERBOSE, Flags.BLT_DUMP, Flags.DUMMY_SELECT, Flags.DUMP_DAE_LOW, Flags.DUMP_INDX_DAE, Flags.OPT_DAE_DUMP, Flags.EXEC_HASH, Flags.PARAM_DLOW_DUMP, Flags.DUMP_ENCAPSULATECONDITIONS, Flags.SHORT_OUTPUT, Flags.COUNT_OPERATIONS, Flags.CGRAPH, Flags.UPDMOD, Flags.STATIC, Flags.TPL_PERF_TIMES, Flags.CHECK_SIMPLIFY, Flags.SCODE_INST, Flags.WRITE_TO_BUFFER, Flags.DUMP_BACKENDDAE_INFO, Flags.GEN_DEBUG_SYMBOLS, Flags.DUMP_STATESELECTION_INFO, Flags.DUMP_EQNINORDER, Flags.SEMILINEAR, Flags.UNCERTAINTIES, Flags.SHOW_START_ORIGIN, Flags.DUMP_SIMCODE, Flags.DUMP_INITIAL_SYSTEM, Flags.GRAPH_INST, Flags.GRAPH_INST_RUN_DEP, Flags.GRAPH_INST_GEN_GRAPH, Flags.GRAPH_INST_SHOW_GRAPH, Flags.DUMP_CONST_REPL, Flags.SHOW_EQUATION_SOURCE, Flags.LS_ANALYTIC_JACOBIAN, Flags.NLS_ANALYTIC_JACOBIAN, Flags.INLINE_SOLVER, Flags.HPCOM, Flags.INITIALIZATION, Flags.INLINE_FUNCTIONS, Flags.DUMP_SCC_GRAPHML, Flags.TEARING_DUMPVERBOSE, Flags.DISABLE_SINGLE_FLOW_EQ, Flags.DUMP_DISCRETEVARS_INFO, Flags.ADDITIONAL_GRAPHVIZ_DUMP, Flags.INFO_XML_OPERATIONS, Flags.HPCOM_DUMP, Flags.RESOLVE_LOOPS_DUMP, Flags.DISABLE_WINDOWS_PATH_CHECK_WARNING, Flags.DISABLE_RECORD_CONSTRUCTOR_OUTPUT, Flags.IMPL_ODE, Flags.EVAL_FUNC_DUMP, Flags.PRINT_STRUCTURAL, Flags.ITERATION_VARS, Flags.ALLOW_RECORD_TOO_MANY_FIELDS, Flags.HPCOM_MEMORY_OPT, Flags.DUMP_SYNCHRONOUS, Flags.STRIP_PREFIX, Flags.DO_SCODE_DEP, Flags.SHOW_INST_CACHE_INFO, Flags.DUMP_UNIT, Flags.DUMP_EQ_UNIT, Flags.DUMP_EQ_UNIT_STRUCT, Flags.SHOW_DAE_GENERATION, Flags.RESHUFFLE_POST, Flags.SHOW_EXPANDABLE_INFO, Flags.DUMP_HOMOTOPY, Flags.OMC_RELOCATABLE_FUNCTIONS, Flags.GRAPHML, Flags.USEMPI, Flags.DUMP_CSE, Flags.DUMP_CSE_VERBOSE, Flags.NO_START_CALC, Flags.CONSTJAC, Flags.VISUAL_XML, Flags.VECTORIZE, Flags.CHECK_EXT_LIBS, Flags.RUNTIME_STATIC_LINKING, Flags.SORT_EQNS_AND_VARS, Flags.DUMP_SIMPLIFY_LOOPS, Flags.DUMP_RTEARING, Flags.DIS_SYMJAC_FMI20, Flags.EVAL_OUTPUT_ONLY, Flags.HARDCODED_START_VALUES, Flags.DUMP_FUNCTIONS, Flags.DEBUG_DIFFERENTIATION, Flags.DEBUG_DIFFERENTIATION_VERBOSE, Flags.FMU_EXPERIMENTAL, Flags.DUMP_DGESV, Flags.MULTIRATE_PARTITION, Flags.DUMP_EXCLUDED_EXP, Flags.DEBUG_ALGLOOP_JACOBIAN, Flags.DISABLE_JACSCC, Flags.FORCE_NLS_ANALYTIC_JACOBIAN, Flags.DUMP_LOOPS, Flags.DUMP_LOOPS_VERBOSE, Flags.SKIP_INPUT_OUTPUT_SYNTACTIC_SUGAR, Flags.OMC_RECORD_ALLOC_WORDS, Flags.TOTAL_TEARING_DUMP, Flags.TOTAL_TEARING_DUMPVERBOSE, Flags.PARALLEL_CODEGEN, Flags.SERIALIZED_SIZE, Flags.BACKEND_KEEP_ENV_GRAPH, Flags.DUMPBACKENDINLINE, Flags.DUMPBACKENDINLINE_VERBOSE, Flags.BLT_MATRIX_DUMP, Flags.LIST_REVERSE_WRONG_ORDER, Flags.PARTITION_INITIALIZATION, Flags.EVAL_PARAM_DUMP, Flags.NF_UNITCHECK, Flags.DISABLE_COLORING, Flags.MERGE_ALGORITHM_SECTIONS, Flags.WARN_NO_NOMINAL, Flags.REDUCE_DAE, Flags.IGNORE_CYCLES, Flags.ALIAS_CONFLICTS, Flags.SUSAN_MATCHCONTINUE_DEBUG, Flags.OLD_FE_UNITCHECK, Flags.EXEC_STAT_EXTRA_GC, Flags.DEBUG_DAEMODE, Flags.NF_SCALARIZE, Flags.NF_EVAL_CONST_ARG_FUNCS, Flags.NF_EXPAND_OPERATIONS, Flags.NF_API, Flags.NF_API_DYNAMIC_SELECT, Flags.NF_API_NOISE, Flags.FMI20_DEPENDENCIES, Flags.WARNING_MINMAX_ATTRIBUTES, Flags.NF_EXPAND_FUNC_ARGS, Flags.DUMP_JL, Flags.DUMP_ASSC, Flags.SPLIT_CONSTANT_PARTS_SYMJAC, Flags.NF_DUMP_FLAT, Flags.DUMP_FORCE_FMI_ATTRIBUTES, Flags.DUMP_FORCE_FMI_INTERNAL_VARIABLES, Flags.NF_PARALLEL, Flags.NF_SEPARATE_INDEX_REDUCTION)::List #= This is a list of all configuration flags. A flag can not be used unless it's =# diff --git a/test/Models/CoupledPenduliNormal.mo b/test/Models/CoupledPenduliNormal.mo new file mode 100644 index 0000000..113595b --- /dev/null +++ b/test/Models/CoupledPenduliNormal.mo @@ -0,0 +1,38 @@ +model CoupledPenduli + model Table + parameter Real m = 100.; + public Real x(start=0.,fixed=true); + protected Real u(start=0.,fixed=true); + public Real f; + equation + m*der(u) - f = 0; + der(x) = u; + end Table; + model Pendulum + parameter Real m = 1.; + parameter Real l = 1.; + parameter Real g = 9.81; + parameter Real theta0 = 0; + public Real x; + public Real f; + protected Real a(start=l*sin(theta0),fixed=true); + protected Real b(start=-l*cos(theta0),fixed=false); + protected Real u(start=0.,fixed=true); + protected Real v(start=0.,fixed=true); + protected Real lambda; + equation + m*der(u) - lambda*(a-x) = 0; + m*der(v) - lambda*b + m*g = 0; + der(a) = u; + der(b) = v; + (a-x)^2 + b^2 - l^2 = 0; + f - lambda*(a-x)/l = 0; + end Pendulum; + Table tb; + Pendulum p1(theta0 = 0.1); + Pendulum p2(theta0 = 0.0); +equation + p1.x = tb.x; + p2.x = tb.x; + tb.f + p1.f + p2.f = 0; +end CoupledPenduli; diff --git a/test/Models/CoupledPenduliStructural.mo b/test/Models/CoupledPenduliStructural.mo new file mode 100644 index 0000000..41aa851 --- /dev/null +++ b/test/Models/CoupledPenduliStructural.mo @@ -0,0 +1,38 @@ +model CoupledPenduli + model Table + parameter Real m = 100.; + public Real x(start=0.,fixed=true); + protected Real u(start=0.,fixed=true); + public Real f; + equation + m*der(u) - f = 0; + der(x) = u; + end Table; + model Pendulum + parameter Real m = 1.; + parameter Real l = 1.; + parameter Real g = 9.81; + parameter Real theta0 = 0; + public Real x; + public Real f; + protected Real a(start=l*sin(theta0),fixed=true); + protected Real b(start=-l*cos(theta0),fixed=false); + protected Real u(start=0.,fixed=true); + protected Real v(start=0.,fixed=true); + protected Real lambda; + equation + m*der(u) - lambda*(a-x) = 0; + m*der(v) - lambda*b + m*g = 0; + der(a) = u; + der(b) = v; + (a-x)^2 + b^2 - l^2 = 0; + f - lambda*(a-x)/l = 0; + end Pendulum; + structuralmode Table tb; + structuralmode Pendulum p1(theta0 = 0.1); + structuralmode Pendulum p2(theta0 = 0.0); +equation + p1.x = tb.x; + p2.x = tb.x; + tb.f + p1.f + p2.f = 0; +end CoupledPenduli; diff --git a/test/jsonExportTests.jl b/test/jsonExportTests.jl new file mode 100644 index 0000000..6fc98c1 --- /dev/null +++ b/test/jsonExportTests.jl @@ -0,0 +1,121 @@ +#= + JSON exporter tests. + + Exports a self-contained structural-mode model (no MSL) to hierarchy/flat + JSON via OMFrontend.exportJSON and asserts the result against the schema in + docs/structural_mode_json.atd: structural-mode components are deduplicated + into class templates, and per-instance differences surface as parameter + overrides. Array order in the JSON follows Dict iteration, so every lookup + is by name rather than by position. +=# +import JSON + +const _JSON_MODEL_FILE = joinpath(@__DIR__, "Models", "CoupledPenduliStructural.mo") +const _JSON_CLASS_MAP = Dict("p1" => "Pendulum", "p2" => "Pendulum", "tb" => "Table") + +_jsonOutDir = mktempdir() +_jsonRet = OMFrontend.exportJSON("CoupledPenduli", _JSON_MODEL_FILE; + output_dir = _jsonOutDir, base_name = "CP", + class_mapping = _JSON_CLASS_MAP) + +@testset "writes both files and returns their paths" begin + @test _jsonRet.hierarchy_path == joinpath(_jsonOutDir, "CP_hierarchy.json") + @test _jsonRet.flat_path == joinpath(_jsonOutDir, "CP_flat.json") + @test isfile(_jsonRet.hierarchy_path) + @test isfile(_jsonRet.flat_path) +end + +_jsonHier = JSON.parsefile(_jsonRet.hierarchy_path) +_jsonFlat = JSON.parsefile(_jsonRet.flat_path) + +@testset "hierarchy: deduplicated class templates" begin + @test _jsonHier["model"] == "CoupledPenduli" + # p1 and p2 share a fingerprint -> one Pendulum template; tb -> Table. + classes = Dict(c["name"] => c for c in _jsonHier["structural_classes"]) + @test Set(keys(classes)) == Set(["Pendulum", "Table"]) + for c in values(classes) + @test all(haskey(c, k) for k in + ("name", "highest_differentiation_order", + "highest_differentiation_order_variables")) + @test c["highest_differentiation_order"] == 1 + end + @test Set(classes["Pendulum"]["highest_differentiation_order_variables"]) == + Set(["a", "b", "u", "v"]) + @test Set(classes["Table"]["highest_differentiation_order_variables"]) == + Set(["u", "x"]) + # Three components, each tagged with its template class and counts. + comps = Dict(c["name"] => c for c in _jsonHier["structural_components"]) + @test Set(keys(comps)) == Set(["p1", "p2", "tb"]) + @test comps["p1"]["type"] == "Pendulum" + @test comps["p2"]["type"] == "Pendulum" + @test comps["tb"]["type"] == "Table" + @test (comps["p1"]["n_parameters"], comps["p1"]["n_variables"], + comps["p1"]["n_equations"]) == (4, 7, 6) + @test (comps["tb"]["n_parameters"], comps["tb"]["n_variables"], + comps["tb"]["n_equations"]) == (1, 3, 2) + @test length(_jsonHier["coupling_equations"]) == 3 +end + +@testset "flat: templates carry variables/equations" begin + @test _jsonFlat["model"] == "CoupledPenduli" + classes = Dict(c["name"] => c for c in _jsonFlat["structural_classes"]) + @test Set(keys(classes)) == Set(["Pendulum", "Table"]) + @test length(classes["Pendulum"]["variables"]) == 11 + @test length(classes["Pendulum"]["equations"]) == 6 + @test length(classes["Table"]["variables"]) == 4 + @test length(classes["Table"]["equations"]) == 2 + # Variable and equation records carry their ATD-required keys. + v = first(classes["Table"]["variables"]) + @test all(haskey(v, k) for k in + ("name", "type", "variability", "visibility", + "highest_differentiation_order")) + e = first(classes["Table"]["equations"]) + @test all(haskey(e, k) for k in + ("id", "equation", "differentiation_order", "variables_used")) +end + +@testset "flat: per-instance parameter overrides" begin + comps = Dict(c["name"] => c for c in _jsonFlat["components"]) + @test Set(keys(comps)) == Set(["p1", "p2", "tb"]) + @test comps["p1"]["class"] == "Pendulum" + @test comps["p2"]["class"] == "Pendulum" + @test comps["tb"]["class"] == "Table" + # The two Pendulum instances differ only in theta0; one is the template + # representative, so exactly one override (on theta0) is emitted. + overridden = [c for c in _jsonFlat["components"] + if !isempty(get(c, "parameter_overrides", []))] + @test length(overridden) == 1 + @test only(overridden)["name"] in ("p1", "p2") + ov = only(overridden)["parameter_overrides"] + @test only(ov)["parameter"] == "theta0" + @test only(ov)["value"] in ("0.0", "0.1") +end + +@testset "flat: top level and variable/equation cross-reference" begin + # Coupling equations become the top-level section; no top-level variables. + @test length(_jsonFlat["top_level"]["equations"]) == 3 + @test isempty(get(_jsonFlat["top_level"], "variables", [])) + vmap = Dict(m["variable"] => m["equation_ids"] + for m in _jsonFlat["variable_to_equations"]) + # tb.x couples into p1.x = tb.x (top.eq1) and its own der(x) = u (tb.eq2). + @test haskey(vmap, "tb.x") + @test "top.eq1" in vmap["tb.x"] + @test "tb.eq2" in vmap["tb.x"] +end + +@testset "ATD schema export" begin + outdir = mktempdir() + atdPath = OMFrontend.exportATD(output_dir = outdir, base_name = "schema") + @test atdPath == joinpath(outdir, "schema.atd") + @test isfile(atdPath) + schema = read(atdPath, String) + @test occursin("type hierarchy", schema) + @test occursin("type flat_model", schema) + @test occursin("OMFrontend.exportJSON", schema) + # exportJSON(atd=true) writes the same schema alongside the JSON and returns its path. + r = OMFrontend.exportJSON("CoupledPenduli", _JSON_MODEL_FILE; + output_dir = outdir, base_name = "CPatd", atd = true) + @test r.atd_path == joinpath(outdir, "CPatd.atd") + @test isfile(r.atd_path) + @test read(r.atd_path, String) == schema +end diff --git a/test/replaceableTests.jl b/test/replaceableTests.jl index 0a796f0..8e7756d 100644 --- a/test/replaceableTests.jl +++ b/test/replaceableTests.jl @@ -19,14 +19,11 @@ end @test occursin("h_start", s) end -@testset "Replaceable partial function called via partial default (Buildings/PartialMedium pattern)" begin - # UsePartialDefault calls P.compute where P is still the partial default. - # This is invalid Modelica; the frontend should reject it gracefully. - # With the CLASS_TREE_EXPANDED_TREE no-op fix the crash (MethodError) is - # gone -- the error is now a controlled assertion. The @test_broken tracks - # that full redeclaration-context propagation (Fix #2) is still outstanding. - @test_broken begin - (fm, _) = _flattenFM_replaceable("UsePartialDefault", _REPL_PKG_FILE) - true - end +@testset "Replaceable partial function called via partial default is rejected (OMC parity)" begin + # UsePartialDefault calls P.compute where P is left at its partial default + # (AbstractFnPkg2) and never redeclared, so compute is a partial function. + # This is invalid Modelica; OMC rejects it with "P is partial, name lookup + # is not allowed in partial classes." The frontend must reject it too. + @test_throws MetaModelica.MetaModelicaGeneralException _flattenFM_replaceable( + "UsePartialDefault", _REPL_PKG_FILE) end diff --git a/test/runtests.jl b/test/runtests.jl index b853853..4ad8fd0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -81,6 +81,14 @@ end include("replaceableTests.jl") end + @testset "JSON exporter" begin + include("jsonExportTests.jl") + end + + @testset "Separate-index-reduction flatten" begin + include("separateFlattenTests.jl") + end + #= Test components in the MSL If you are a user of this package please submit more tests here. diff --git a/test/separateFlattenTests.jl b/test/separateFlattenTests.jl new file mode 100644 index 0000000..69a25bd --- /dev/null +++ b/test/separateFlattenTests.jl @@ -0,0 +1,34 @@ +#= + Separate-index-reduction flatten tests. + + With `separateIndexReduction` off, a normal assembly model is fully inlined. + With it on, each top-level component is kept as its own entry in + `structuralSubmodels` (reusing the structural-mode storage) so the backend can + run index reduction per component. The flag is set per flatten call, so it + does not leak to later flattens. +=# +const _SEP_MODEL_FILE = joinpath(@__DIR__, "Models", "CoupledPenduliNormal.mo") +_sepNSub(fm) = OMFrontend.Frontend.listLength(fm.structuralSubmodels) + +@testset "flag off: assembly is fully inlined" begin + (fm, _) = OMFrontend.flattenModel("CoupledPenduli", _SEP_MODEL_FILE) + @test _sepNSub(fm) == 0 + @test length(fm.variables) > 0 # component variables inlined at top level +end + +@testset "flag on: each top-level component split out" begin + (fm, _) = OMFrontend.flattenModel("CoupledPenduli", _SEP_MODEL_FILE; + separateIndexReduction = true) + @test _sepNSub(fm) == 3 + names = Set(sm.name for sm in fm.structuralSubmodels) + @test names == Set(["tb", "p1", "p2"]) + # The three coupling equations stay at the top level; the component + # variables move into the submodels. + @test length(fm.equations) == 3 + @test length(fm.variables) == 0 +end + +@testset "flag does not leak to later flattens" begin + (fm, _) = OMFrontend.flattenModel("CoupledPenduli", _SEP_MODEL_FILE) + @test _sepNSub(fm) == 0 +end From a9f75fc93fecb3031788dfe3859bf3af4d47bfbd Mon Sep 17 00:00:00 2001 From: JKRT Date: Sun, 21 Jun 2026 14:06:15 +0200 Subject: [PATCH 5/5] Better naming of the structural-mode improvements --- docs/structural_mode_json.atd | 95 +++++++++++++++++++++++++++++++++++ src/NewFrontend/NFFlatten.jl | 2 +- src/OMFrontend.jl | 32 ++++++------ src/Util/Flags.jl | 4 +- src/Util/FlagsUtil.jl | 2 +- test/runtests.jl | 2 +- test/separateFlattenTests.jl | 6 +-- 7 files changed, 119 insertions(+), 24 deletions(-) create mode 100644 docs/structural_mode_json.atd diff --git a/docs/structural_mode_json.atd b/docs/structural_mode_json.atd new file mode 100644 index 0000000..9d9b1d3 --- /dev/null +++ b/docs/structural_mode_json.atd @@ -0,0 +1,95 @@ +(* ATD type definitions for flat Modelica model JSON export. + These types define the schema for both the hierarchy and flat model JSON + produced by `OMFrontend.exportJSON`. *) + +(* -- Shared types -- *) + +type variability = [ + | Parameter + | Continuous +] + +type visibility = [ + | Public + | Protected +] + +type variable = { + name: string; + type_name : string; + variability: variability; + visibility: visibility; + highest_differentiation_order: int; + ?default_value : string option; + ?attributes: string option; +} + +type equation = { + id: string; + equation: string; + differentiation_order: int; + variables_used: string list; +} + +(* -- Hierarchy JSON -- *) + +type structural_class_summary = { + name: string; + highest_differentiation_order: int; + highest_differentiation_order_variables: string list; +} + +type structural_component = { + name: string; + type_name : string; + n_variables: int; + n_parameters: int; + n_equations: int; +} + +type hierarchy = { + model: string; + structural_classes: structural_class_summary list; + structural_components: structural_component list; + coupling_equations: string list; + ~top_level_variables: string list; +} + +(* -- Flat model JSON -- *) + +type structural_class = { + name: string; + highest_differentiation_order: int; + highest_differentiation_order_variables: string list; + variables: variable list; + equations: equation list; +} + +type parameter_override = { + parameter: string; + value: string; +} + +type component = { + name: string; + class_name : string; + ~parameter_overrides: parameter_override list; +} + +type top_level_section = { + ~variables: variable list; + ~equations: equation list; +} + +type var_equation_mapping = { + variable: string; + equation_ids: string list; +} + +type flat_model = { + model: string; + structural_classes: structural_class list; + components: component list; + top_level: top_level_section; + variable_to_equations: var_equation_mapping list; +} diff --git a/src/NewFrontend/NFFlatten.jl b/src/NewFrontend/NFFlatten.jl index 0c9fb64..4ee6770 100644 --- a/src/NewFrontend/NFFlatten.jl +++ b/src/NewFrontend/NFFlatten.jl @@ -286,7 +286,7 @@ function flattenComponent( every top-level component. The flag is gated on isTopLevel so it does not cascade into a submodel's own internals. =# if c.attributes.isStructuralMode == true || - (isTopLevel && Flags.isSet(Flags.NF_SEPARATE_INDEX_REDUCTION)) + (isTopLevel && Flags.isSet(Flags.NF_SEPARATE_INSTANTIATION)) #@debug "FLATTEN A COMPLEX STRUCTURAL COMPONENT" #= Since this component is structural we do not flatten it. diff --git a/src/OMFrontend.jl b/src/OMFrontend.jl index 32b7ebc..86aa3fb 100644 --- a/src/OMFrontend.jl +++ b/src/OMFrontend.jl @@ -143,13 +143,13 @@ end """ function instantiateSCodeToFM(elementToInstantiate::String, inProgram::SCode.Program; scalarize = true, - separateIndexReduction = false) + separateInstantiation = false) # initialize globals Frontend.Global.initialize() # make sure we have all the flags loaded! # Frontend.Flags.new(Flags.emptyFlags) Frontend.FlagsUtil.set(Frontend.Flags.NF_SCALARIZE, scalarize) - Frontend.FlagsUtil.set(Frontend.Flags.NF_SEPARATE_INDEX_REDUCTION, separateIndexReduction) + Frontend.FlagsUtil.set(Frontend.Flags.NF_SEPARATE_INSTANTIATION, separateInstantiation) local builtinSCode = NFModelicaBuiltinCache["NFModelicaBuiltin"] local program = listReverse(listAppend(builtinSCode, inProgram)) local path = Frontend.AbsynUtil.stringPath(elementToInstantiate) @@ -367,11 +367,11 @@ end Returns the flat representation of a modelica model along with the functions used and define by the model. """ function flattenModel(modelName::String, fileName::String; scalarize = true, - separateIndexReduction = false) + separateInstantiation = false) local absynProgram = parseFile(fileName) local sCodeProgram = translateToSCode(absynProgram) (FM, cache) = instantiateSCodeToFM(modelName, sCodeProgram; scalarize = scalarize, - separateIndexReduction = separateIndexReduction) + separateInstantiation = separateInstantiation) end """ @@ -1013,7 +1013,7 @@ function flattenModelWithLibraries(modelName::String, MSL::Bool = false, MSL_Version::String = "MSL:3.2.3", scalarize::Bool = true, - separateIndexReduction::Bool = false, + separateInstantiation::Bool = false, forceReload::Bool = false) local combined = if isempty(fileName) nil @@ -1036,7 +1036,7 @@ function flattenModelWithLibraries(modelName::String, combined = listAppend(combined, LIBRARY_CACHE[mslKey]) end (FM, cache) = instantiateSCodeToFM(modelName, combined; scalarize = scalarize, - separateIndexReduction = separateIndexReduction) + separateInstantiation = separateInstantiation) end @@ -1068,27 +1068,27 @@ end """ ``` -enableSeparateIndexReduction() +enableSeparateInstantiation() ``` Flatten each top-level component into its own structural submodel (`FLAT_MODEL.structuralSubmodels`) so the backend can run index reduction -separately per component. Equivalent to passing `separateIndexReduction = true` -to `flattenModel`/`instantiateSCodeToFM`. Disable with `disableSeparateIndexReduction()`. +separately per component. Equivalent to passing `separateInstantiation = true` +to `flattenModel`/`instantiateSCodeToFM`. Disable with `disableSeparateInstantiation()`. """ -function enableSeparateIndexReduction() - status = FlagsUtil.enableDebug(Flags.NF_SEPARATE_INDEX_REDUCTION) - @info "Enabled Flags.NF_SEPARATE_INDEX_REDUCTION. Old status was $(status)" +function enableSeparateInstantiation() + status = FlagsUtil.enableDebug(Flags.NF_SEPARATE_INSTANTIATION) + @info "Enabled Flags.NF_SEPARATE_INSTANTIATION. Old status was $(status)" end """ ``` -disableSeparateIndexReduction() +disableSeparateInstantiation() ``` Restore the default whole-model flattening (top-level components are inlined). """ -function disableSeparateIndexReduction() - status = FlagsUtil.disableDebug(Flags.NF_SEPARATE_INDEX_REDUCTION) - @info "Disabled Flags.NF_SEPARATE_INDEX_REDUCTION. Old status was $(status)" +function disableSeparateInstantiation() + status = FlagsUtil.disableDebug(Flags.NF_SEPARATE_INSTANTIATION) + @info "Disabled Flags.NF_SEPARATE_INSTANTIATION. Old status was $(status)" end Base.show(io::IO, ::MIME"text/plain", fm::OMFrontend.Frontend.FLAT_MODEL) = begin diff --git a/src/Util/Flags.jl b/src/Util/Flags.jl index d2a1e48..5852246 100644 --- a/src/Util/Flags.jl +++ b/src/Util/Flags.jl @@ -1446,10 +1446,10 @@ const NF_PARALLEL = false, Gettext.gettext("Opt-in parallelism for OMFrontend phases beyond Absyn-to-SCode (e.g. future parallel instantiation). The Absyn-to-SCode parallel branch is proven safe and runs unconditionally based on `Threads.nthreads()`; this flag does not control it. Reserved for opt-in branches whose correctness is not yet proven. Default off."), )::DebugFlag -const NF_SEPARATE_INDEX_REDUCTION = +const NF_SEPARATE_INSTANTIATION = DEBUG_FLAG( 186, - "nfSeparateIndexReduction", + "nfSeparateInstantiation", false, Gettext.gettext("Flatten each top-level component into its own structural submodel so index reduction can run separately per component. Default off."), )::DebugFlag diff --git a/src/Util/FlagsUtil.jl b/src/Util/FlagsUtil.jl index 53f0c3a..b9b3444 100644 --- a/src/Util/FlagsUtil.jl +++ b/src/Util/FlagsUtil.jl @@ -62,7 +62,7 @@ import ..Gettext #= indices). =# -const allDebugFlags = list(Flags.FAILTRACE, Flags.CEVAL, Flags.CHECK_BACKEND_DAE, Flags.PARMODAUTO, Flags.PTHREADS, Flags.EVENTS, Flags.DUMP_INLINE_SOLVER, Flags.EVAL_FUNC, Flags.GEN, Flags.DYN_LOAD, Flags.GENERATE_CODE_CHEAT, Flags.CGRAPH_GRAPHVIZ_FILE, Flags.CGRAPH_GRAPHVIZ_SHOW, Flags.GC_PROF, Flags.CHECK_DAE_CREF_TYPE, Flags.CHECK_ASUB, Flags.INSTANCE, Flags.CACHE, Flags.RML, Flags.TAIL, Flags.LOOKUP, Flags.PATTERNM_SKIP_FILTER_UNUSED_AS_BINDINGS, Flags.PATTERNM_ALL_INFO, Flags.PATTERNM_DCE, Flags.PATTERNM_MOVE_LAST_EXP, Flags.EXPERIMENTAL_REDUCTIONS, Flags.EVAL_PARAM, Flags.TYPES, Flags.SHOW_STATEMENT, Flags.DUMP, Flags.DUMP_GRAPHVIZ, Flags.EXEC_STAT, Flags.TRANSFORMS_BEFORE_DUMP, Flags.DAE_DUMP_GRAPHV, Flags.INTERACTIVE_TCP, Flags.INTERACTIVE_CORBA, Flags.INTERACTIVE_DUMP, Flags.RELIDX, Flags.DUMP_REPL, Flags.DUMP_FP_REPL, Flags.DUMP_PARAM_REPL, Flags.DUMP_PP_REPL, Flags.DUMP_EA_REPL, Flags.DEBUG_ALIAS, Flags.TEARING_DUMP, Flags.JAC_DUMP, Flags.JAC_DUMP2, Flags.JAC_DUMP_EQN, Flags.JAC_WARNINGS, Flags.DUMP_SPARSE, Flags.DUMP_SPARSE_VERBOSE, Flags.BLT_DUMP, Flags.DUMMY_SELECT, Flags.DUMP_DAE_LOW, Flags.DUMP_INDX_DAE, Flags.OPT_DAE_DUMP, Flags.EXEC_HASH, Flags.PARAM_DLOW_DUMP, Flags.DUMP_ENCAPSULATECONDITIONS, Flags.SHORT_OUTPUT, Flags.COUNT_OPERATIONS, Flags.CGRAPH, Flags.UPDMOD, Flags.STATIC, Flags.TPL_PERF_TIMES, Flags.CHECK_SIMPLIFY, Flags.SCODE_INST, Flags.WRITE_TO_BUFFER, Flags.DUMP_BACKENDDAE_INFO, Flags.GEN_DEBUG_SYMBOLS, Flags.DUMP_STATESELECTION_INFO, Flags.DUMP_EQNINORDER, Flags.SEMILINEAR, Flags.UNCERTAINTIES, Flags.SHOW_START_ORIGIN, Flags.DUMP_SIMCODE, Flags.DUMP_INITIAL_SYSTEM, Flags.GRAPH_INST, Flags.GRAPH_INST_RUN_DEP, Flags.GRAPH_INST_GEN_GRAPH, Flags.GRAPH_INST_SHOW_GRAPH, Flags.DUMP_CONST_REPL, Flags.SHOW_EQUATION_SOURCE, Flags.LS_ANALYTIC_JACOBIAN, Flags.NLS_ANALYTIC_JACOBIAN, Flags.INLINE_SOLVER, Flags.HPCOM, Flags.INITIALIZATION, Flags.INLINE_FUNCTIONS, Flags.DUMP_SCC_GRAPHML, Flags.TEARING_DUMPVERBOSE, Flags.DISABLE_SINGLE_FLOW_EQ, Flags.DUMP_DISCRETEVARS_INFO, Flags.ADDITIONAL_GRAPHVIZ_DUMP, Flags.INFO_XML_OPERATIONS, Flags.HPCOM_DUMP, Flags.RESOLVE_LOOPS_DUMP, Flags.DISABLE_WINDOWS_PATH_CHECK_WARNING, Flags.DISABLE_RECORD_CONSTRUCTOR_OUTPUT, Flags.IMPL_ODE, Flags.EVAL_FUNC_DUMP, Flags.PRINT_STRUCTURAL, Flags.ITERATION_VARS, Flags.ALLOW_RECORD_TOO_MANY_FIELDS, Flags.HPCOM_MEMORY_OPT, Flags.DUMP_SYNCHRONOUS, Flags.STRIP_PREFIX, Flags.DO_SCODE_DEP, Flags.SHOW_INST_CACHE_INFO, Flags.DUMP_UNIT, Flags.DUMP_EQ_UNIT, Flags.DUMP_EQ_UNIT_STRUCT, Flags.SHOW_DAE_GENERATION, Flags.RESHUFFLE_POST, Flags.SHOW_EXPANDABLE_INFO, Flags.DUMP_HOMOTOPY, Flags.OMC_RELOCATABLE_FUNCTIONS, Flags.GRAPHML, Flags.USEMPI, Flags.DUMP_CSE, Flags.DUMP_CSE_VERBOSE, Flags.NO_START_CALC, Flags.CONSTJAC, Flags.VISUAL_XML, Flags.VECTORIZE, Flags.CHECK_EXT_LIBS, Flags.RUNTIME_STATIC_LINKING, Flags.SORT_EQNS_AND_VARS, Flags.DUMP_SIMPLIFY_LOOPS, Flags.DUMP_RTEARING, Flags.DIS_SYMJAC_FMI20, Flags.EVAL_OUTPUT_ONLY, Flags.HARDCODED_START_VALUES, Flags.DUMP_FUNCTIONS, Flags.DEBUG_DIFFERENTIATION, Flags.DEBUG_DIFFERENTIATION_VERBOSE, Flags.FMU_EXPERIMENTAL, Flags.DUMP_DGESV, Flags.MULTIRATE_PARTITION, Flags.DUMP_EXCLUDED_EXP, Flags.DEBUG_ALGLOOP_JACOBIAN, Flags.DISABLE_JACSCC, Flags.FORCE_NLS_ANALYTIC_JACOBIAN, Flags.DUMP_LOOPS, Flags.DUMP_LOOPS_VERBOSE, Flags.SKIP_INPUT_OUTPUT_SYNTACTIC_SUGAR, Flags.OMC_RECORD_ALLOC_WORDS, Flags.TOTAL_TEARING_DUMP, Flags.TOTAL_TEARING_DUMPVERBOSE, Flags.PARALLEL_CODEGEN, Flags.SERIALIZED_SIZE, Flags.BACKEND_KEEP_ENV_GRAPH, Flags.DUMPBACKENDINLINE, Flags.DUMPBACKENDINLINE_VERBOSE, Flags.BLT_MATRIX_DUMP, Flags.LIST_REVERSE_WRONG_ORDER, Flags.PARTITION_INITIALIZATION, Flags.EVAL_PARAM_DUMP, Flags.NF_UNITCHECK, Flags.DISABLE_COLORING, Flags.MERGE_ALGORITHM_SECTIONS, Flags.WARN_NO_NOMINAL, Flags.REDUCE_DAE, Flags.IGNORE_CYCLES, Flags.ALIAS_CONFLICTS, Flags.SUSAN_MATCHCONTINUE_DEBUG, Flags.OLD_FE_UNITCHECK, Flags.EXEC_STAT_EXTRA_GC, Flags.DEBUG_DAEMODE, Flags.NF_SCALARIZE, Flags.NF_EVAL_CONST_ARG_FUNCS, Flags.NF_EXPAND_OPERATIONS, Flags.NF_API, Flags.NF_API_DYNAMIC_SELECT, Flags.NF_API_NOISE, Flags.FMI20_DEPENDENCIES, Flags.WARNING_MINMAX_ATTRIBUTES, Flags.NF_EXPAND_FUNC_ARGS, Flags.DUMP_JL, Flags.DUMP_ASSC, Flags.SPLIT_CONSTANT_PARTS_SYMJAC, Flags.NF_DUMP_FLAT, Flags.DUMP_FORCE_FMI_ATTRIBUTES, Flags.DUMP_FORCE_FMI_INTERNAL_VARIABLES, Flags.NF_PARALLEL, Flags.NF_SEPARATE_INDEX_REDUCTION)::List +const allDebugFlags = list(Flags.FAILTRACE, Flags.CEVAL, Flags.CHECK_BACKEND_DAE, Flags.PARMODAUTO, Flags.PTHREADS, Flags.EVENTS, Flags.DUMP_INLINE_SOLVER, Flags.EVAL_FUNC, Flags.GEN, Flags.DYN_LOAD, Flags.GENERATE_CODE_CHEAT, Flags.CGRAPH_GRAPHVIZ_FILE, Flags.CGRAPH_GRAPHVIZ_SHOW, Flags.GC_PROF, Flags.CHECK_DAE_CREF_TYPE, Flags.CHECK_ASUB, Flags.INSTANCE, Flags.CACHE, Flags.RML, Flags.TAIL, Flags.LOOKUP, Flags.PATTERNM_SKIP_FILTER_UNUSED_AS_BINDINGS, Flags.PATTERNM_ALL_INFO, Flags.PATTERNM_DCE, Flags.PATTERNM_MOVE_LAST_EXP, Flags.EXPERIMENTAL_REDUCTIONS, Flags.EVAL_PARAM, Flags.TYPES, Flags.SHOW_STATEMENT, Flags.DUMP, Flags.DUMP_GRAPHVIZ, Flags.EXEC_STAT, Flags.TRANSFORMS_BEFORE_DUMP, Flags.DAE_DUMP_GRAPHV, Flags.INTERACTIVE_TCP, Flags.INTERACTIVE_CORBA, Flags.INTERACTIVE_DUMP, Flags.RELIDX, Flags.DUMP_REPL, Flags.DUMP_FP_REPL, Flags.DUMP_PARAM_REPL, Flags.DUMP_PP_REPL, Flags.DUMP_EA_REPL, Flags.DEBUG_ALIAS, Flags.TEARING_DUMP, Flags.JAC_DUMP, Flags.JAC_DUMP2, Flags.JAC_DUMP_EQN, Flags.JAC_WARNINGS, Flags.DUMP_SPARSE, Flags.DUMP_SPARSE_VERBOSE, Flags.BLT_DUMP, Flags.DUMMY_SELECT, Flags.DUMP_DAE_LOW, Flags.DUMP_INDX_DAE, Flags.OPT_DAE_DUMP, Flags.EXEC_HASH, Flags.PARAM_DLOW_DUMP, Flags.DUMP_ENCAPSULATECONDITIONS, Flags.SHORT_OUTPUT, Flags.COUNT_OPERATIONS, Flags.CGRAPH, Flags.UPDMOD, Flags.STATIC, Flags.TPL_PERF_TIMES, Flags.CHECK_SIMPLIFY, Flags.SCODE_INST, Flags.WRITE_TO_BUFFER, Flags.DUMP_BACKENDDAE_INFO, Flags.GEN_DEBUG_SYMBOLS, Flags.DUMP_STATESELECTION_INFO, Flags.DUMP_EQNINORDER, Flags.SEMILINEAR, Flags.UNCERTAINTIES, Flags.SHOW_START_ORIGIN, Flags.DUMP_SIMCODE, Flags.DUMP_INITIAL_SYSTEM, Flags.GRAPH_INST, Flags.GRAPH_INST_RUN_DEP, Flags.GRAPH_INST_GEN_GRAPH, Flags.GRAPH_INST_SHOW_GRAPH, Flags.DUMP_CONST_REPL, Flags.SHOW_EQUATION_SOURCE, Flags.LS_ANALYTIC_JACOBIAN, Flags.NLS_ANALYTIC_JACOBIAN, Flags.INLINE_SOLVER, Flags.HPCOM, Flags.INITIALIZATION, Flags.INLINE_FUNCTIONS, Flags.DUMP_SCC_GRAPHML, Flags.TEARING_DUMPVERBOSE, Flags.DISABLE_SINGLE_FLOW_EQ, Flags.DUMP_DISCRETEVARS_INFO, Flags.ADDITIONAL_GRAPHVIZ_DUMP, Flags.INFO_XML_OPERATIONS, Flags.HPCOM_DUMP, Flags.RESOLVE_LOOPS_DUMP, Flags.DISABLE_WINDOWS_PATH_CHECK_WARNING, Flags.DISABLE_RECORD_CONSTRUCTOR_OUTPUT, Flags.IMPL_ODE, Flags.EVAL_FUNC_DUMP, Flags.PRINT_STRUCTURAL, Flags.ITERATION_VARS, Flags.ALLOW_RECORD_TOO_MANY_FIELDS, Flags.HPCOM_MEMORY_OPT, Flags.DUMP_SYNCHRONOUS, Flags.STRIP_PREFIX, Flags.DO_SCODE_DEP, Flags.SHOW_INST_CACHE_INFO, Flags.DUMP_UNIT, Flags.DUMP_EQ_UNIT, Flags.DUMP_EQ_UNIT_STRUCT, Flags.SHOW_DAE_GENERATION, Flags.RESHUFFLE_POST, Flags.SHOW_EXPANDABLE_INFO, Flags.DUMP_HOMOTOPY, Flags.OMC_RELOCATABLE_FUNCTIONS, Flags.GRAPHML, Flags.USEMPI, Flags.DUMP_CSE, Flags.DUMP_CSE_VERBOSE, Flags.NO_START_CALC, Flags.CONSTJAC, Flags.VISUAL_XML, Flags.VECTORIZE, Flags.CHECK_EXT_LIBS, Flags.RUNTIME_STATIC_LINKING, Flags.SORT_EQNS_AND_VARS, Flags.DUMP_SIMPLIFY_LOOPS, Flags.DUMP_RTEARING, Flags.DIS_SYMJAC_FMI20, Flags.EVAL_OUTPUT_ONLY, Flags.HARDCODED_START_VALUES, Flags.DUMP_FUNCTIONS, Flags.DEBUG_DIFFERENTIATION, Flags.DEBUG_DIFFERENTIATION_VERBOSE, Flags.FMU_EXPERIMENTAL, Flags.DUMP_DGESV, Flags.MULTIRATE_PARTITION, Flags.DUMP_EXCLUDED_EXP, Flags.DEBUG_ALGLOOP_JACOBIAN, Flags.DISABLE_JACSCC, Flags.FORCE_NLS_ANALYTIC_JACOBIAN, Flags.DUMP_LOOPS, Flags.DUMP_LOOPS_VERBOSE, Flags.SKIP_INPUT_OUTPUT_SYNTACTIC_SUGAR, Flags.OMC_RECORD_ALLOC_WORDS, Flags.TOTAL_TEARING_DUMP, Flags.TOTAL_TEARING_DUMPVERBOSE, Flags.PARALLEL_CODEGEN, Flags.SERIALIZED_SIZE, Flags.BACKEND_KEEP_ENV_GRAPH, Flags.DUMPBACKENDINLINE, Flags.DUMPBACKENDINLINE_VERBOSE, Flags.BLT_MATRIX_DUMP, Flags.LIST_REVERSE_WRONG_ORDER, Flags.PARTITION_INITIALIZATION, Flags.EVAL_PARAM_DUMP, Flags.NF_UNITCHECK, Flags.DISABLE_COLORING, Flags.MERGE_ALGORITHM_SECTIONS, Flags.WARN_NO_NOMINAL, Flags.REDUCE_DAE, Flags.IGNORE_CYCLES, Flags.ALIAS_CONFLICTS, Flags.SUSAN_MATCHCONTINUE_DEBUG, Flags.OLD_FE_UNITCHECK, Flags.EXEC_STAT_EXTRA_GC, Flags.DEBUG_DAEMODE, Flags.NF_SCALARIZE, Flags.NF_EVAL_CONST_ARG_FUNCS, Flags.NF_EXPAND_OPERATIONS, Flags.NF_API, Flags.NF_API_DYNAMIC_SELECT, Flags.NF_API_NOISE, Flags.FMI20_DEPENDENCIES, Flags.WARNING_MINMAX_ATTRIBUTES, Flags.NF_EXPAND_FUNC_ARGS, Flags.DUMP_JL, Flags.DUMP_ASSC, Flags.SPLIT_CONSTANT_PARTS_SYMJAC, Flags.NF_DUMP_FLAT, Flags.DUMP_FORCE_FMI_ATTRIBUTES, Flags.DUMP_FORCE_FMI_INTERNAL_VARIABLES, Flags.NF_PARALLEL, Flags.NF_SEPARATE_INSTANTIATION)::List #= This is a list of all configuration flags. A flag can not be used unless it's =# diff --git a/test/runtests.jl b/test/runtests.jl index 4ad8fd0..f9aab19 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -85,7 +85,7 @@ end include("jsonExportTests.jl") end - @testset "Separate-index-reduction flatten" begin + @testset "Separate instantiation" begin include("separateFlattenTests.jl") end diff --git a/test/separateFlattenTests.jl b/test/separateFlattenTests.jl index 69a25bd..91fd7e0 100644 --- a/test/separateFlattenTests.jl +++ b/test/separateFlattenTests.jl @@ -1,7 +1,7 @@ #= - Separate-index-reduction flatten tests. + Separate-instantiation flatten tests. - With `separateIndexReduction` off, a normal assembly model is fully inlined. + With `separateInstantiation` off, a normal assembly model is fully inlined. With it on, each top-level component is kept as its own entry in `structuralSubmodels` (reusing the structural-mode storage) so the backend can run index reduction per component. The flag is set per flatten call, so it @@ -18,7 +18,7 @@ end @testset "flag on: each top-level component split out" begin (fm, _) = OMFrontend.flattenModel("CoupledPenduli", _SEP_MODEL_FILE; - separateIndexReduction = true) + separateInstantiation = true) @test _sepNSub(fm) == 3 names = Set(sm.name for sm in fm.structuralSubmodels) @test names == Set(["tb", "p1", "p2"])