diff --git a/REQUIRE b/REQUIRE index c697fb6..92f14f4 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,5 +1,6 @@ julia 0.6 PyPlot +JSON ModiaMath Unitful DataStructures diff --git a/src/language/Execution.jl b/src/language/Execution.jl index 3962795..a7d83d8 100644 --- a/src/language/Execution.jl +++ b/src/language/Execution.jl @@ -2,7 +2,7 @@ Modia module for executing a model including code generation and calling DAE solver. * Original developer: Toivo Henningsson, Lund -* Developer: Hilding Elmqvist, Mogram AB +* Developer: Hilding Elmqvist, Mogram AB * Copyright (c) 2016-2018: Hilding Elmqvist, Toivo Henningsson, Martin Otter * License: MIT (expat) @@ -13,7 +13,7 @@ export simulate_ida export setOptions using Base.Meta: quot, isexpr -using DataStructures.OrderedDict +using DataStructures: OrderedDict @static if ! (VERSION < v"0.7.0-DEV.2005") using LinearAlgebra using SparseArrays @@ -26,18 +26,18 @@ import ModiaMath #0.7 using Unitful using ..ModiaLogging -const PrintJSONsolved = false +const PrintJSONsolved = false const showCode = false # Show the code for initialization and residual calculations const logComputations = false # Insert logging of variable values in the code const callF = false -const showJacobian = false +const showJacobian = false global logTiming # Show timing for each major task, simulate twice to see effect of compilation time. global storeEliminated -global handleImpulses +global handleImpulses -function setOptions(options) +function setOptions(options) global storeEliminated = true if haskey(options, :storeEliminated) global storeEliminated = options[:storeEliminated] @@ -62,7 +62,7 @@ function split_variables(src::VariableDict) for (name, var) in src if !isa(var, Instance) && (!isa(var, Variable) || var.variability <= parameter) params[name] = var - else + else vars[name] = var end end @@ -79,7 +79,7 @@ function subs(s::Subs, ex::Symbolic, complete::Bool) else ex end end - + function subs(s::Subs, ex::Expr, complete::Bool) if isexpr(ex, :quote) ex @@ -139,7 +139,7 @@ function code_eliminated_func(fname, unpack, eliminated_computations, vars, x::S # if T != Any || T != Float64; T = Any; end # Hack to handle units if typeof(T) <: Unitful.Unitlike; T = Float64; end # To handle units # @show T, string(var) - + if !isempty(dims); T = Array{T,length(dims)}; end push!(alloc_eliminated, :($res_name = $results[$(string(name))] = Vector{$(quot(T))}(0)) ) @@ -147,7 +147,7 @@ function code_eliminated_func(fname, unpack, eliminated_computations, vars, x::S end # @show eliminated_computations # @show push_eliminated - + eliminated_code = quote function $(fname)($results, $ts, $xs, $der_xs) $(alloc_eliminated...) @@ -187,7 +187,7 @@ function substituteExpr(ex, equations, s) ex = eq.args[2] break end - end + end end end cond = subs(s, ex, true) @@ -208,13 +208,13 @@ end const letArgs = 1 else const letArgs = 2 -end - +end + function prepare_ida(instance::Instance, first_F_args, initial_bindings::AbstractDict{Symbol,Any}; store_eliminated = false, need_eliminated_f = false) proceed = zeros(Bool,1) global F_Dict - + params, vars = split_variables(vars_of(instance)) for (name, var) in vars check_start(var, name) @@ -250,7 +250,7 @@ function prepare_ida(instance::Instance, first_F_args, initial_bindings::Abstrac function getType(vars, v) vars[v].typ end - + modeConditions = [] for eq in eqs_of(instance) if isexpr(eq, :(:=), 2) @@ -287,13 +287,13 @@ function prepare_ida(instance::Instance, first_F_args, initial_bindings::Abstrac println("Mode condition: ", prettyPrint(condExpr), " is $evalCond at time=$time") oldCond = evalCond end - + global oldCond if evalCond != oldCond println("Mode change: ", prettyPrint(condExpr), " became ", evalCond, " at time ", time) end oldCond = evalCond - + e = if evalCond; eq.args[2] else eq.args[3] end e = subs(s, e, true) @@ -310,8 +310,8 @@ function prepare_ida(instance::Instance, first_F_args, initial_bindings::Abstrac end end end - - + + # error("Unsupported equation type: ", eq) end end @@ -325,13 +325,13 @@ function prepare_ida(instance::Instance, first_F_args, initial_bindings::Abstrac is_diffstate = GetField(This(), name) in d s = get_start(var) if isa(s, AbstractArray) - append!(x0, vec(s)) -# @show name, vec(s) + append!(x0, vec(s)) +# @show name, vec(s) append!(diffstates, fill(is_diffstate, length(s))) - else + else push!(x0, s) # push!(x0, ustrip(s)) -# @show name, s +# @show name, s push!(diffstates, is_diffstate) end end @@ -350,7 +350,7 @@ function prepare_ida(instance::Instance, first_F_args, initial_bindings::Abstrac println() end end -=# +=# # Create mapping between states and state vector @@ -362,15 +362,15 @@ function prepare_ida(instance::Instance, first_F_args, initial_bindings::Abstrac else state_size = 0 end - + if state_size > 0 ModiaLogging.increaseLogCategory(:DynamicModel) else ModiaLogging.increaseLogCategory(:StaticModel) end - + loglnModia("statesize = ", state_size) - + # if ! haskey(F_Dict, modeConditions) @gensym x der_x r @@ -379,25 +379,25 @@ function prepare_ida(instance::Instance, first_F_args, initial_bindings::Abstrac if logComputations push!(unpack, :( - if ! $proceed[1]; + if ! $proceed[1]; println("Press enter to continue, q to stop, p to proceed: "); l = readline(STDIN); if l != "" && l[1] == 'q'; error("quit") elseif l != "" && l[1] == 'p'; $proceed[1] = true end end)) push!(unpack, :(if ! $proceed[1]; println("\nUnpack:") end)) end - + # println("State vector allocation:") - initials = [] + initials = [] i = 1 for ((name, var), offset) in zip(states, state_offsets) der_name = der_name_of(name) - + if true # diffstates[i] # Wonder about reason??? push!(unpack, :(global $name = $(code_state_read(x, offset, get_dims(var)...))) ) push!(unpack, :($der_name = $(code_state_read(der_x, offset, get_dims(var)...))) ) else push!(unpack, :(global $name = $(code_state_read(der_x, offset, get_dims(var)...))) ) - end - i += prod(get_dims(var)) + end + i += prod(get_dims(var)) if logComputations push!(unpack, :(if ! $proceed[1]; @show $name, $der_name end) ) end @@ -437,7 +437,7 @@ function prepare_ida(instance::Instance, first_F_args, initial_bindings::Abstrac end loglnModia("residual_size = ", residual_size) @assert state_size == residual_size - + residual_offsets = cumsum(vcat([1], residual_sizes[1:end-1])) # @show residual_offsets @@ -489,13 +489,13 @@ function prepare_ida(instance::Instance, first_F_args, initial_bindings::Abstrac $(F_code) end end - + if showCode println("\nFUNCTION F CODE") @show F_code end - + # F = Eval(F_code) F = eval(Module(), F_code) @@ -506,7 +506,7 @@ function prepare_ida(instance::Instance, first_F_args, initial_bindings::Abstrac else (F, initial_eliminated) = F_Dict[modeConditions] end -=# +=# if need_eliminated_f eliminated_code = code_eliminated_func( @@ -532,7 +532,7 @@ end global_elim_results = Vector{Vector}() - + # Temporary definitions import ModiaMath.ModiaToModiaMath.ModiaSimulationModel #is_output_point(m::ModiaSimulationModel) = true # Should not always be true! @@ -559,19 +559,19 @@ end function simulate_ida(instance::Instance, t, args...; kwargs...) simulate_ida(instance, collect(Float64, t), args...; kwargs...) end - + function simulate_ida(instance::Instance, t::Vector{Float64}, jac::Union{SparseMatrixCSC{Bool,Int},Nothing};# =nothing; log=false, relTol=1e-4, maxSparsity=0.1, store_eliminated=storeEliminated) - + if PrintJSONsolved printJSONforSolvedEquations(instance) end - + initial_bindings = Dict{Symbol,Any}(time_symbol => t[1]) initial_m = ModiaSimulationModel() - + initial_bindings[simulationModel_symbol] = initial_m prep = prepare_ida(instance, [simulationModel_symbol], initial_bindings, store_eliminated=storeEliminated, need_eliminated_f=storeEliminated) @@ -585,8 +585,8 @@ function simulate_ida(instance::Instance, t::Vector{Float64}, if callF || handleImpulses || showJacobian callResidualFunction(F, callF, handleImpulses, showJacobian, x0, der_x0, diffstates, instance) end - - xNames = fill("[]",length(x0)) + + xNames = fill("[]",length(x0)) ii = 0 for (name,var) in states ii += 1 @@ -597,7 +597,7 @@ function simulate_ida(instance::Instance, t::Vector{Float64}, dimsArray = collect(dims) if length(dimsArray) == 1 for j in 1:dimsArray[1] - xNames[state_offsets[ii]+j-1] = name*"["*string(j)*"]" + xNames[state_offsets[ii]+j-1] = name*"["*string(j)*"]" end else xNames[state_offsets[ii]] = name*"[]" @@ -608,8 +608,8 @@ function simulate_ida(instance::Instance, t::Vector{Float64}, # @show xNames start = now() - - if length(x0) > 0 + + if length(x0) > 0 if false m = ModiaSimulationModel(model_name_of(instance), F, x0, der_x0, jac; xw_states=diffstates, maxSparsity=maxSparsity, nc=1, nz=initial_m.nz_preInitial, @@ -617,7 +617,7 @@ function simulate_ida(instance::Instance, t::Vector{Float64}, else m = ModiaSimulationModel(string(model_name_of(instance)), F, x0; maxSparsity=maxSparsity, nc=1, nz=initial_m.nz_preInitial, jac=jac, x_fixed=diffstates) - end + end if logTiming print("\n ModiaMath: ") @time ModiaMath.ModiaToModiaMath.simulate(m, t; log=log, tolRel=relTol) @@ -637,7 +637,7 @@ function simulate_ida(instance::Instance, t::Vector{Float64}, x_res = t der_x_res = t end - + results = extract_results_ida(x_res, der_x_res, states, state_offsets, params) # @show keys(results) # @show now()-start @@ -665,7 +665,7 @@ function callResidualFunction(F, callF, handleImpulses, showJacobian, x0, der_x0 mF = ModiaSimulationModel() r0 = fill(0.0, n) w = [] - + Base.invokelatest(F, mF, 0, x0, der_x0, r0, w) # @show x0 der_x0 r0 @@ -694,7 +694,7 @@ function callResidualFunction(F, callF, handleImpulses, showJacobian, x0, der_x0 end end else - independent += 1 + independent += 1 end end @@ -716,11 +716,11 @@ function callResidualFunction(F, callF, handleImpulses, showJacobian, x0, der_x0 end end else - independent += 1 + independent += 1 end end end - + if showJacobian @show A @show size(A) @@ -735,7 +735,7 @@ function callResidualFunction(F, callF, handleImpulses, showJacobian, x0, der_x0 println("The implicit system matrix does not have full rank.") end end - + if handleImpulses oldx0 = copy(x0) X0 = copy(x0) @@ -754,11 +754,11 @@ function callResidualFunction(F, callF, handleImpulses, showJacobian, x0, der_x0 params, vars = split_variables(vars_of(instance)) names = collect(keys(vars)) -#= +#= for i in 1:length(x0) if abs(X0[i]-oldx0[i]) > 1E5 println("Dirac impulse in variable ", names[i]) - end + end end =# for i in der_index @@ -790,7 +790,7 @@ JSON.lower(t::This) = "this." JSON.lower(s::SIUnits.SIUnit) = string(s) =# -""" +""" Experiemental code for printing the AST of solved equations in JSON format """ function printJSONforSolvedEquations(instance) @@ -830,7 +830,7 @@ makeJSON(ex) = get(operator_table, string(ex), string(ex)) function makeJSON(ex::Array{Any}) [makeJSON(e) for e in ex] end - + function makeJSON(ex::Expr) if isexpr(ex, :quote) || isexpr(ex, :line) nothing diff --git a/src/language/Instantiation.jl b/src/language/Instantiation.jl index 1b08de7..ca88173 100644 --- a/src/language/Instantiation.jl +++ b/src/language/Instantiation.jl @@ -2,7 +2,7 @@ Modia module for instantiation and flattening of models. * Original developer: Toivo Henningsson, Lund -* Developer: Hilding Elmqvist, Mogram AB +* Developer: Hilding Elmqvist, Mogram AB * Copyright (c) 2016-2018: Hilding Elmqvist, Toivo Henningsson, Martin Otter * License: MIT (expat) @@ -24,13 +24,13 @@ using Base.Meta:quot, isexpr using DataStructures: OrderedDict #0.7 using SparseArrays @static if VERSION < v"0.7.0-DEV.2005" - Nothing = Void + Nothing = Void AbstractDict = Associative end import ModiaMath #0.7 using Unitful -using ..ModiaLogging +using ..ModiaLogging #using ..Synchronous const shortSyntax = true @@ -62,17 +62,17 @@ mutable struct Variable # {T,n} state::Bool property::Property end -# The variability, type and info are added as attributes in the type for uniform treatment. +# The variability, type and info are added as attributes in the type for uniform treatment. # Input/output, etc should also be added. -Variable(;value=nothing, info="", unit=if typeof(value) <: Unitful.Quantity; Unitful.unit(value) else Unitful.NoUnits end, - displayUnit=unit, +Variable(;value=nothing, info="", unit=if typeof(value) <: Unitful.Quantity; Unitful.unit(value) else Unitful.NoUnits end, + displayUnit=unit, min=nothing, max=nothing, start=nothing, fixed::Bool=false, nominal=nothing, - variability=continuous, T=if value==nothing; Any else typeof(value) end, size=if value==nothing; nothing else Base.size(value) end, flow::Bool=false, state::Bool=true, property=general) = - Variable(variability, T, size, value, + variability=continuous, T=if value==nothing; Any else typeof(value) end, size=if value==nothing; nothing else Base.size(value) end, flow::Bool=false, state::Bool=true, property=general) = + Variable(variability, T, size, value, unit, displayUnit, min, max, start, fixed, nominal, info, flow, state, property) - - + + function Base.show(io::IO, v::Variable) print(io, "Variable(") @@ -125,7 +125,7 @@ function Base.show(io::IO, v::Variable) println(io, ")") end -#= +#= function show(io::IO, x::Volt) print(io, "Volt") nothing @@ -173,7 +173,7 @@ end function Base.show(io::IO, g::GetField) if shortSyntax - print(io, g.base, ".", g.name) + print(io, g.base, ".", g.name) else print(io, "GetField(", g.base, ", ", g.name, ")") end @@ -181,7 +181,7 @@ end "AST node for the derivative of a `Symbolic` node." struct Der <: Symbolic - base::Symbolic + base::Symbolic end #= function Base.show(io::IO, d::Der) @@ -193,7 +193,7 @@ function Base.show(io::IO, d::Der) if shortSyntax print(io, "der(", d.base, ")") else - print(io, "Der(", d.base, ")") + print(io, "Der(", d.base, ")") end end @@ -202,7 +202,7 @@ struct This <: Symbolic end #= -function Base.show(io::IO, this::This) +function Base.show(io::IO, this::This) print(io, "this") end =# @@ -211,14 +211,14 @@ function Base.show(io::IO, this::This) if shortSyntax print(io, "this") else - print(io, "This()") + print(io, "This()") end end "Representation of a connect equation, used in the equations list." struct Connect - a::Symbolic - b::Symbolic + a::Symbolic + b::Symbolic end function Base.show(io::IO, c::Connect) @@ -308,7 +308,7 @@ function recode(ex::Expr) return :( $(quot(Connect))($(recode(args[2])), $(recode(args[3]))) ) else print("The connect statement takes two arguments: $ex") - end + end end args = map(recode, ex.args) @@ -410,7 +410,7 @@ end function code_variable(ex::Expr, varnames) @assert isexpr(ex, :(=), 2) lhs, rhs = ex.args - + # if typeof(rhs) == Expr && (rhs.head == call || rhs.head == :call) if typeof(rhs) == Expr && rhs.head == :call args = rhs.args @@ -434,10 +434,10 @@ function code_variable(ex::Expr, varnames) rhs = Expr(:call, :Variable, Expr(:kw, :typ, typ), sta, args[2:end]...) else rhs = Expr(:call, :Variable, Expr(:kw, :typ, typ), args[2:end]...) - end + end end end - + rhs = recode_initializer(rhs) locals = code_init_locals(varnames) fdef = :( ($this_symbol,time)->($locals; $rhs) ) @@ -670,7 +670,7 @@ mutable struct Instance F_post::Vector{Any} end function Instance(model_name::Symbol, variables, equations, partial) - Instance(model_name, VariableDict(variables), + Instance(model_name, VariableDict(variables), collect(Any, equations), partial, [], [], [], []) end @@ -689,7 +689,7 @@ function Base.show(io::IO, inst::Instance) end println(io, " ]") end - + println(io, ")") end =# @@ -745,7 +745,7 @@ end function initialize!(instance::Instance, iv::InitVariable, time::Float64, kwargs::AbstractDict) # @show iv.fdef - add_variable!(instance, iv.name, + add_variable!(instance, iv.name, as_field_value(haskey(kwargs, iv.name) ? kwargs[iv.name] : iv.init(instance, time), time) ) @@ -911,7 +911,7 @@ function to_access(connector::Connection, field::Union{Symbol,Nothing}) end function flatten(instance::Instance) - flat = Flat(VariableDict(), [], + flat = Flat(VariableDict(), [], Dict{Symbol, Symbol}(), Dict{Symbol, Dict}()) flatten!(flat, "", instance) @@ -990,15 +990,18 @@ function prettyfy(ex::Expr) Expr(ex.head, [prettyfy(arg) for arg in ex.args]...) end end - + # Pretty printing of expressions -const oper = Base.Operators #; [+, -]] -#const operator_table = [getfield(oper,name) => name for name in -# filter(name->isdefined(oper,name), names(oper))] -const operator_table = Dict(getfield(oper,name) => name for name in - filter(name->isdefined(oper,name), names(oper))) +const oper = [:!, :(!=), :(!==), :%, :&, :*, :+, :-, :/, ://, :<, :<:, :<<, :(<=), + :<|, :(==), :(===), :>, :>:, :(>=), :>>, :>>>, :\, :^, :colon, + :ctranspose, :getindex, :hcat, :hvcat, :setindex!, :transpose, :vcat, + :xor, :|, :|>, :~, :×, :÷, :∈, :∉, :∋, :∌, :∘, :√, :∛, :∩, :∪, :≠, :≤, + :≥, :⊆, :⊈, :⊊, :⊻, :⋅] + +const operator_table = Dict(getfield(Base,name) => name for name in + filter(name->isdefined(Base,name), oper)) prettyPrint(ex) = get(operator_table, ex, ex) Array{Any} @@ -1014,4 +1017,4 @@ function prettyPrint(e::Expr) end -end +end diff --git a/src/symbolic/Utilities.jl b/src/symbolic/Utilities.jl index 9f07e80..bbe8977 100644 --- a/src/symbolic/Utilities.jl +++ b/src/symbolic/Utilities.jl @@ -1,7 +1,7 @@ """ Modia module with utility functions. -* Developer: Hilding Elmqvist, Mogram AB +* Developer: Hilding Elmqvist, Mogram AB * First version: July 2016 * Copyright (c) 2016-2018: Hilding Elmqvist, Toivo Henningsson, Martin Otter * License: MIT (expat) @@ -15,11 +15,11 @@ using Base.Meta: quot, isexpr using Unitful using ..Instantiation -using ..ModiaLogging +using ..ModiaLogging export @show_io, printSymbolList, showModel, showInstance, checkSizes, printJSON -using Base.show_unquoted +using Base: show_unquoted # Version of @show for any stream macro show_io(io, exs...) @@ -44,14 +44,14 @@ function printSymbolList(label, symbols, numbering=false, vertical=false, A=[]) if vertical loglnModia() else - logModia(", ") + logModia(", ") end end if numbering if vertical logModia(lpad(i, 5, " "), ": ") else - logModia(i, ": ") + logModia(i, ": ") end end if vertical @@ -59,10 +59,10 @@ function printSymbolList(label, symbols, numbering=false, vertical=false, A=[]) else logModia(prettyfy(symbols[i])) end - if A !=[] + if A !=[] if A[i] != 0 logModia("A[$i] = $(A[i])") - end + end end end if length(symbols) > maxSymbols @@ -170,10 +170,10 @@ function showInstance(inst, indent="") loglnModia("------") @show inst loglnModia("------") -=# +=# newIndent = string(indent, " ") loglnModia("@model ", inst.model_name, " begin") - for key in keys(inst.variables) + for key in keys(inst.variables) if isa(key, Instance) logModia(indent, " ", key, " = ") showInstance(inst.variables[key], newIndent) @@ -183,7 +183,7 @@ function showInstance(inst, indent="") else keyname = replace(string(key), "." => "_") end - logModia(indent, " ", keyname, " = ") + logModia(indent, " ", keyname, " = ") showVariable(inst.variables[key]) end end @@ -195,7 +195,7 @@ function showInstance(inst, indent="") end loglnModia(indent, " end") loglnModia(indent, "end") - + end function checkSizes(VSizes, ESizes) @@ -209,7 +209,7 @@ function checkSizes(VSizes, ESizes) loglnModia() scalarV = sum(length(zeros(v)) for v in VSizes) scalarE = sum(length(zeros(e)) for e in ESizes) - if scalarV != scalarE + if scalarV != scalarE error("Scalarized system matrix is not square: $scalarE x $scalarV") ok = false else @@ -250,7 +250,7 @@ function printJSON(file, inst::Instance, fullName, name, parent="", indent="", l loglnModia(file, indent, "{") loglnModia(file, indent, "\"id\": \"$(fullName)\",") loglnModia(file, indent, "\"class\": \"$(inst.model_name)\",") - + params, unknowns = split_variables(vars_of(inst)) if length(params) > 0 loglnModia(file, indent, "\"parameters\": {") @@ -260,14 +260,14 @@ function printJSON(file, inst::Instance, fullName, name, parent="", indent="", l i += 1 logModia(file, indent1, "\"", n, "\"", " : ", p) if i < length(params) - loglnModia(file, ",") + loglnModia(file, ",") else - loglnModia(file) + loglnModia(file) end - end + end loglnModia(file, indent, "},") end - + loglnModia(file, indent, "\"labels\": [{\"text\": \"$name\"}],") if isPort(inst) orientation = if length(search(string(parent), "G")) > 0; "\"NORTH\"" elseif length(search(string(name), "p")) > 0 || length(search(string(name), "in")) > 0; "\"WEST\"" else "\"EAST\"" end @@ -279,12 +279,12 @@ function printJSON(file, inst::Instance, fullName, name, parent="", indent="", l loglnModia(file, indent, "\"width\": $size,") loglnModia(file, indent, "\"height\": $size") end - + first = true for (n,v) in inst.variables if isa(v, Instance) && isPort(v) && level > 1 # length(search(string(n), "n")) == 0 if first - loglnModia(file, indent, ", \"ports\": [") + loglnModia(file, indent, ", \"ports\": [") else loglnModia(file, indent, ", ") end @@ -295,12 +295,12 @@ function printJSON(file, inst::Instance, fullName, name, parent="", indent="", l if ! first loglnModia(file, indent, "]") end - + first = true for (n,v) in inst.variables if isa(v, Instance) && (! isPort(v) || level == 1) # || (isa(v, Instance) && isPort(v) && length(search(string(n), "n")) > 0) if first - loglnModia(file, indent, ", \"children\": [") + loglnModia(file, indent, ", \"children\": [") else loglnModia(file, indent, ", ") end @@ -311,13 +311,13 @@ function printJSON(file, inst::Instance, fullName, name, parent="", indent="", l if ! first loglnModia(file, indent, "]") end - + first = true id = 0 for e in inst.equations if isa(e, Connect) if first - loglnModia(file, indent, ", \"edges\": [") + loglnModia(file, indent, ", \"edges\": [") else loglnModia(file, indent, ", ") end @@ -328,13 +328,13 @@ function printJSON(file, inst::Instance, fullName, name, parent="", indent="", l loglnModia(file, indent, " \"source\": \"$(e.a.base.name)\",") loglnModia(file, indent, " \"sourcePort\": \"$(string(e.a.base.name)*string(e.a.name))\",") else - loglnModia(file, indent, " \"source\": \"$(e.a.name)\",") + loglnModia(file, indent, " \"source\": \"$(e.a.name)\",") end if isa(e.b.base, GetField) loglnModia(file, indent, " \"target\": \"$(e.b.base.name)\",") loglnModia(file, indent, " \"targetPort\": \"$(string(e.b.base.name)*string(e.b.name))\"}") else - loglnModia(file, indent, " \"target\": \"$(e.b.name)\"}") + loglnModia(file, indent, " \"target\": \"$(e.b.name)\"}") end end end