11// SPDX-License-Identifier: AGPL-3.0-or-later
22
3- import type { FmuOptions } from "@modelscript/core" ;
3+ import type { FmuArchiveOptions } from "@modelscript/core" ;
44import {
55 Context ,
66 ModelicaDAE ,
77 ModelicaFlattener ,
88 ModelicaLinter ,
99 ModelicaSimulator ,
10+ buildFmuArchive ,
1011 generateFmu ,
1112} from "@modelscript/core" ;
1213import Modelica from "@modelscript/tree-sitter-modelica" ;
@@ -27,12 +28,16 @@ interface ExportFmuArgs {
2728 stopTime ?: number ;
2829 "step-size" ?: number ;
2930 stepSize ?: number ;
31+ "xml-only" ?: boolean ;
32+ xmlOnly ?: boolean ;
33+ type ?: string ;
34+ source ?: boolean ;
3035}
3136
3237// eslint-disable-next-line @typescript-eslint/no-empty-object-type
3338export const ExportFmu : CommandModule < { } , ExportFmuArgs > = {
3439 command : "export-fmu <name> <paths..>" ,
35- describe : "Export a Modelica model as an FMI 2.0 Co-Simulation FMU model description " ,
40+ describe : "Export a Modelica model as an FMI 2.0 FMU (Model Exchange & Co-Simulation) " ,
3641 // eslint-disable-next-line @typescript-eslint/no-explicit-any
3742 builder : ( ( yargs : any ) => {
3843 return yargs
@@ -49,7 +54,7 @@ export const ExportFmu: CommandModule<{}, ExportFmuArgs> = {
4954 } )
5055 . option ( "output" , {
5156 alias : "o" ,
52- description : "output file path (default: <name>.fmu.xml)" ,
57+ description : "output file path (default: <name>.fmu or <name>.fmu .xml)" ,
5358 type : "string" ,
5459 } )
5560 . option ( "description" , {
@@ -67,6 +72,22 @@ export const ExportFmu: CommandModule<{}, ExportFmuArgs> = {
6772 . option ( "step-size" , {
6873 description : "default experiment step size" ,
6974 type : "number" ,
75+ } )
76+ . option ( "xml-only" , {
77+ description : "output only the modelDescription.xml (no archive)" ,
78+ type : "boolean" ,
79+ default : false ,
80+ } )
81+ . option ( "type" , {
82+ description : "FMU type: 'me' (Model Exchange), 'cs' (Co-Simulation), 'both' (default)" ,
83+ type : "string" ,
84+ default : "both" ,
85+ choices : [ "me" , "cs" , "both" ] ,
86+ } )
87+ . option ( "source" , {
88+ description : "include C source files in the FMU archive" ,
89+ type : "boolean" ,
90+ default : true ,
7091 } ) ;
7192 // eslint-disable-next-line @typescript-eslint/no-explicit-any
7293 } ) as any ,
@@ -138,26 +159,70 @@ export const ExportFmu: CommandModule<{}, ExportFmuArgs> = {
138159 const simulator = new ModelicaSimulator ( dae ) ;
139160 simulator . prepare ( ) ;
140161
141- // Generate FMU model description
142- const fmuOptions : FmuOptions = {
143- modelIdentifier : args . name . replace ( / \. / g, "_" ) ,
144- description : args . description ,
145- generationTool : "ModelScript CLI" ,
146- startTime : args . startTime ?? args [ "start-time" ] ,
147- stopTime : args . stopTime ?? args [ "stop-time" ] ,
148- stepSize : args . stepSize ?? args [ "step-size" ] ,
162+ // FMU type flags
163+ const fmuType = {
164+ modelExchange : args . type === "me" || args . type === "both" ,
165+ coSimulation : args . type === "cs" || args . type === "both" ,
149166 } ;
150167
151- const result = generateFmu ( dae , fmuOptions , simulator . stateVars ) ;
168+ const modelIdentifier = args . name . replace ( / \. / g, "_" ) ;
169+
170+ if ( args . xmlOnly || args [ "xml-only" ] ) {
171+ // ── XML-only mode (original behavior) ──
172+ const result = generateFmu (
173+ dae ,
174+ {
175+ modelIdentifier,
176+ description : args . description ,
177+ generationTool : "ModelScript CLI" ,
178+ startTime : args . startTime ?? args [ "start-time" ] ,
179+ stopTime : args . stopTime ?? args [ "stop-time" ] ,
180+ stepSize : args . stepSize ?? args [ "step-size" ] ,
181+ fmuType,
182+ } ,
183+ simulator . stateVars ,
184+ ) ;
185+
186+ const outputPath = args . output ?? `${ modelIdentifier } .fmu.xml` ;
187+ fs . writeFileSync ( outputPath , result . modelDescriptionXml , "utf-8" ) ;
152188
153- // Write output
154- const outputPath = args . output ?? `${ args . name . replace ( / \. / g, "_" ) } .fmu.xml` ;
155- fs . writeFileSync ( outputPath , result . modelDescriptionXml , "utf-8" ) ;
189+ console . log ( `FMU model description written to: ${ outputPath } ` ) ;
190+ console . log ( ` Variables: ${ result . scalarVariables . length } ` ) ;
191+ console . log ( ` Outputs: ${ result . modelStructure . outputs . length } ` ) ;
192+ console . log ( ` Derivatives: ${ result . modelStructure . derivatives . length } ` ) ;
193+ console . log ( ` Initial unknowns: ${ result . modelStructure . initialUnknowns . length } ` ) ;
194+ } else {
195+ // ── Full FMU archive mode ──
196+ const archiveOptions : FmuArchiveOptions = {
197+ modelIdentifier,
198+ description : args . description ,
199+ generationTool : "ModelScript CLI" ,
200+ startTime : args . startTime ?? args [ "start-time" ] ,
201+ stopTime : args . stopTime ?? args [ "stop-time" ] ,
202+ stepSize : args . stepSize ?? args [ "step-size" ] ,
203+ fmuType,
204+ includeSources : args . source !== false ,
205+ includeModelJson : true ,
206+ } ;
156207
157- console . log ( `FMU model description written to: ${ outputPath } ` ) ;
158- console . log ( ` Variables: ${ result . scalarVariables . length } ` ) ;
159- console . log ( ` Outputs: ${ result . modelStructure . outputs . length } ` ) ;
160- console . log ( ` Derivatives: ${ result . modelStructure . derivatives . length } ` ) ;
161- console . log ( ` Initial unknowns: ${ result . modelStructure . initialUnknowns . length } ` ) ;
208+ const result = buildFmuArchive ( dae , archiveOptions , simulator ) ;
209+ const outputPath = args . output ?? `${ modelIdentifier } .fmu` ;
210+
211+ fs . writeFileSync ( outputPath , result . archive ) ;
212+
213+ const types = [ ] ;
214+ if ( fmuType . modelExchange ) types . push ( "Model Exchange" ) ;
215+ if ( fmuType . coSimulation ) types . push ( "Co-Simulation" ) ;
216+
217+ console . log ( `FMU archive written to: ${ outputPath } ` ) ;
218+ console . log ( ` Type: ${ types . join ( " + " ) } ` ) ;
219+ console . log ( ` GUID: ${ result . fmuResult . guid } ` ) ;
220+ console . log ( ` Variables: ${ result . fmuResult . scalarVariables . length } ` ) ;
221+ console . log ( ` States: ${ result . fmuResult . modelStructure . derivatives . length } ` ) ;
222+ console . log ( ` Files: ${ result . files . length } ` ) ;
223+ for ( const f of result . files ) {
224+ console . log ( ` ${ f } ` ) ;
225+ }
226+ }
162227 } ,
163228} ;
0 commit comments