In SysML v1, we use parametric diagrams to capture simulation workflows. Is there an equivalent construct in SysML v2 that can represent simulation workflows and model integration—specifically to pass inputs and intermediate results between models, and ultimately propagate them to final system outputs?
Hello,
I understand you want to connect the different models to say, e.g., that the activity pin is bound to some value property on a port.
If this is what you mean, there is no need for other diagram types in SysML v2. All the different aspects that used to be on separate diagrams in v1 are now fully integrated into a single model, so you can just add a binding (or sometimes a subsetting) or a flow between different attribute and item usages to model how data travels throughout the system.
In fact, everything that a parametric diagram could do is now covered by expressions, calculations, and attributes, fully integrated with all other modeling elements.
If you have an example, I can show you how to model it in v2.
Hi Vince, Thank you for your response. I have a sysml v2 model as below. Does it do what you described, or any improvements can be made to add bindings, or flow as you mentioned. I made this example based on you Christmas lessons.
package PSP_Actions {
private import ScalarValues::\*;
private import SI::\*;
*// ---------------------------------------------------------------------------*
*// Attribute definition used to bundle results (optional but convenient)*
*// Think of this like a struct or record returned by an analysis.*
*// ---------------------------------------------------------------------------*
attribute def CampaignMetrics {
*// Higher is better – used as an optimization objective*
attribute scienceScore : Real;
*// Total data generated during the campaign (megabits)*
attribute dataVolume_Mb : Real;
*// Average electrical power draw during the campaign*
attribute avgPower_W : Real;
*// Peak thermal loading experienced during perihelion*
attribute peakThermalLoad : Real;
*// True if all constraints are satisfied*
attribute feasible : Boolean;
}
*// ---------------------------------------------------------------------------*
*// Leaf action: configure instruments*
*// This represents setting instrument modes and sampling rates.*
*// ---------------------------------------------------------------------------*
action def ConfigureInstruments {
*// Fraction of time instruments are active (0.0 = off, 1.0 = always on)*
*// MDAO design variable*
in attribute instrumentDutyCycle : Real;
*// Sampling cadence in seconds (lower = higher data rate)*
*// MDAO design variable*
in attribute cadence_s : Real;
*// Computed average electrical power consumption*
out attribute avgPower_W : Real;
*// Computed science data rate*
out attribute dataRate_Mbps : Real;
doc
/\* avgPower_W and dataRate_Mbps are computed by an external
\* instrument performance model during execution.
\*/
}
*// ---------------------------------------------------------------------------*
*// Leaf action: estimate thermal loading*
*// Represents simplified thermal analysis at perihelion.*
*// ---------------------------------------------------------------------------*
action def EstimateThermalLoad {
*// Closest solar approach distance (astronomical units)*
*// Strong driver of thermal environment*
in attribute perihelion_AU : Real;
*// Attitude configuration (e.g., heat shield pointing vs science pointing)*
in attribute attitudeMode : String;
*// Peak thermal load (normalized or physical units, your choice)*
out attribute peakThermalLoad : Real;
}
*// ---------------------------------------------------------------------------*
*// Leaf action: plan downlink*
*// Models how much data can be transmitted to Earth.*
*// ---------------------------------------------------------------------------*
action def PlanDownlink {
*// Downlink bit rate supported by comms configuration*
in attribute downlinkRate_Mbps : Real;
*// Total contact time with ground stations*
in attribute contactTime_hr : Real;
*// Data volume that needs to be downlinked*
in attribute dataToDownlink_Mb : Real;
*// Data volume actually transmitted*
out attribute dataDownlinked_Mb : Real;
}
*// ===========================================================================*
*// COMPOSITE ACTION*
*// ===========================================================================*
*// This is the \*main action\* you will:*
*// - sweep in a DOE*
*// - optimize in MDAO*
*// - connect to SPDM execution later*
*// ===========================================================================*
action def PlanPerihelionScienceCampaign {
doc
/\* Plans and evaluates a perihelion science campaign for Parker Solar Probe.
\*
\* This action is intentionally parameterized so it can be:
\* - executed repeatedly
\* - driven by MDAO
\*/
*// -----------------------------------------------------------------------*
*// INPUT PARAMETERS (Design variables / knobs)*
*// -----------------------------------------------------------------------*
*// Solar distance during campaign – drives thermal constraints*
in attribute perihelion_AU : Real;
*// Length of the science campaign window*
in attribute campaignDuration_hr : Real;
*// Instrument duty cycle (fraction of time active)*
in attribute instrumentDutyCycle : Real;
*// Sampling cadence (seconds between samples)*
in attribute cadence_s : Real;
*// Communications downlink rate*
in attribute downlinkRate_Mbps : Real;
*// Available ground contact time*
in attribute contactTime_hr : Real;
*// Spacecraft attitude configuration*
in attribute attitudeMode : String;
*// -----------------------------------------------------------------------*
*// LIMITS / CONSTRAINTS*
*// These could be fixed or also treated as design variables later.*
*// -----------------------------------------------------------------------*
*// Maximum allowable average power draw*
in attribute maxAvgPower_W : Real default 200;
*// Maximum allowable thermal load (normalized)*
in attribute maxThermalLoad : Real default 1.0;
*// -----------------------------------------------------------------------*
*// OUTPUT PARAMETERS (Objectives / constraints)*
*// -----------------------------------------------------------------------*
*// Scalar objective to maximize*
out attribute scienceScore : Real;
*// Total data volume produced*
out attribute dataVolume_Mb : Real;
*// Feasibility flag (used as hard constraint)*
out attribute feasible : Boolean;
*// -----------------------------------------------------------------------*
*// LOCAL VARIABLES (referential features)*
*// Think of these as local variables in a function.*
*// -----------------------------------------------------------------------*
ref attribute avgPower_W : Real;
ref attribute dataRate_Mbps : Real;
ref attribute peakThermalLoad : Real;
ref attribute dataDownlinked_Mb : Real;
*// -----------------------------------------------------------------------*
*// ACTION FLOW (Lesson 17 constructs)*
*// -----------------------------------------------------------------------*
*// Start of the action*
first start;
*// STEP 1: Configure instruments*
*// Computes power draw and science data rate*
then action cfg : ConfigureInstruments {
in attribute :>> instrumentDutyCycle;
in attribute :>> cadence_s;
}
*// Capture outputs into local variables*
then assign avgPower_W := cfg.avgPower_W;
then assign dataRate_Mbps := cfg.dataRate_Mbps;
*// STEP 2: Estimate thermal load at perihelion*
then action therm : EstimateThermalLoad {
in attribute :>> perihelion_AU;
in attribute :>> attitudeMode;
}
then assign peakThermalLoad := therm.peakThermalLoad;
*// STEP 3: Compute total data produced*
*// (data rate × duration × seconds/hour ÷ bits/byte)*
then assign dataVolume_Mb := (dataRate_Mbps \* campaignDuration_hr \* 3600) / 8;
*// STEP 4: Parallel evaluation*
*// - one branch scores the science*
*// - one branch checks downlink feasibility*
then fork;
*// -----------------------------*
*// Branch A: Science scoring*
*// -----------------------------*
then scoreCampaign;
action scoreCampaign {
*// If power and thermal limits are respected,*
*// compute a weighted science score*
then if avgPower_W <= maxAvgPower_W and peakThermalLoad <= maxThermalLoad {
then assign scienceScore :=
dataVolume_Mb \*
(1 - (avgPower_W / maxAvgPower_W) \* 0.2) \*
(1 - (peakThermalLoad / maxThermalLoad) \* 0.3);
} else {
*// Violating limits yields zero science value*
then assign scienceScore := 0;
}
then j;
}
*// -----------------------------*
*// Branch B: Downlink planning*
*// -----------------------------*
then scheduleDownlink;
action scheduleDownlink {
action dl : PlanDownlink {
in attribute :>> downlinkRate_Mbps;
in attribute :>> contactTime_hr;
in attribute :>> dataToDownlink_Mb = dataVolume_Mb;
}
then assign dataDownlinked_Mb := dl.dataDownlinked_Mb;
then j;
}
*// Synchronize parallel branches*
join j;
*// STEP 5: Final feasibility check*
*// Used as a hard constraint in MDAO*
then if (
avgPower_W <= maxAvgPower_W and
peakThermalLoad <= maxThermalLoad and
dataDownlinked_Mb >= 0.8 \* dataVolume_Mb
) {
then assign feasible := true;
} else {
then assign feasible := false;
}
}
}
I made some changes based on your feedback. Please review again. Thank you!
package PSP_Actions {
private import ScalarValues::\*;
private import SI::\*;
*// ---------------------------------------------------------------------------*
*// Attribute definition used to bundle results (optional but convenient)*
*// Think of this like a struct or record returned by an analysis.*
*// ---------------------------------------------------------------------------*
item def CampaignMetrics {
*// Higher is better – used as an optimization objective*
attribute scienceScore : Real;
*// Total data generated during the campaign (megabits)*
attribute dataVolume_Mb : Real;
*// Average electrical power draw during the campaign*
attribute avgPower_W : Real;
*// Peak thermal loading experienced during perihelion*
attribute peakThermalLoad : Real;
*// True if all constraints are satisfied*
attribute feasible : Boolean;
}
*// ---------------------------------------------------------------------------*
*// Leaf action: configure instruments*
*// This represents setting instrument modes and sampling rates.*
*// ---------------------------------------------------------------------------*
action def ConfigureInstruments {
*// Fraction of time instruments are active (0.0 = off, 1.0 = always on)*
*// MDAO design variable*
in attribute instrumentDutyCycle : Real;
*// Sampling cadence in seconds (lower = higher data rate)*
*// MDAO design variable*
in attribute cadence_s : Real;
*// Attitude configuration (e.g., heat shield pointing vs science pointing)*
in attribute attitudeMode : String;
*// Computed average electrical power consumption*
out attribute avgPower_W : Real;
*// Computed science data rate*
out attribute dataRate_Mbps : Real;
doc
/\* avgPower_W and dataRate_Mbps are computed by an external
\* instrument performance model during execution.
\*/
}
*// ---------------------------------------------------------------------------*
*// Leaf action: estimate thermal loading*
*// Represents simplified thermal analysis at perihelion.*
*// ---------------------------------------------------------------------------*
action def EstimateThermalLoad {
*// Closest solar approach distance (astronomical units)*
*// Strong driver of thermal environment*
in attribute perihelion_AU : Real;
*// Attitude configuration (e.g., heat shield pointing vs science pointing)*
in attribute attitudeMode : String;
*// Peak thermal load (normalized or physical units, your choice)*
out attribute peakThermalLoad : Real;
}
*// ---------------------------------------------------------------------------*
*// Leaf action: plan downlink*
*// Models how much data can be transmitted to Earth.*
*// ---------------------------------------------------------------------------*
action def PlanDownlink {
*// Downlink bit rate supported by comms configuration*
in attribute downlinkRate_Mbps : Real;
*// Total contact time with ground stations*
in attribute contactTime_hr : Real;
*// Data volume that needs to be downlinked*
in attribute dataToDownlink_Mb : Real;
*// Data volume actually transmitted*
out attribute dataDownlinked_Mb : Real;
}
*// ---------------------------------------------------------------------------*
*// Leaf action: compute total data volume*
*// ---------------------------------------------------------------------------*
action def ComputeTotalDataVolume {
doc
/\* Computes total data volume produced during the campaign. \*/
in attribute dataRate_Mbps : Real;
in attribute campaignDuration_hr : Real;
out attribute dataVolume_Mb = (dataRate_Mbps \* campaignDuration_hr \* 3600) / 8;
}
*// ===========================================================================*
*// LEAF ACTION: Score Science Campaign*
*// ===========================================================================*
action def scoreScienceCampaign {
*// If power and thermal limits are respected,*
*// compute a weighted science score*
in attribute maxAvgPower_W : Real;
in attribute maxThermalLoad : Real;
in attribute avgPower_W : Real;
in attribute peakThermalLoad : Real;
in attribute dataVolume_Mb : Real;
out scienceScore : Real;
if avgPower_W <= maxAvgPower_W and peakThermalLoad <= maxThermalLoad {
assign scienceScore :=
dataVolume_Mb \*
(1 - (avgPower_W / maxAvgPower_W) \* 0.2) \*
(1 - (peakThermalLoad / maxThermalLoad) \* 0.3);
} else {
*// Violating limits yields zero science value*
assign scienceScore := 0;
}
}
*// ===========================================================================*
*// LEAF ACTION: Final Feasibility Check*
*// ===========================================================================*
action def FinalFeasibilityCheck {
doc
/\* Checks if the science campaign meets all constraints.
\* Used as a hard constraint in MDAO.
\*/
in attribute maxAvgPower_W : Real;
in attribute maxThermalLoad : Real;
in attribute dataDownlinked_Mb : Real;
in attribute dataVolume_Mb : Real;
in attribute avgPower_W : Real;
in attribute peakThermalLoad : Real;
out feasible : Real;
if (
avgPower_W <= maxAvgPower_W and
peakThermalLoad <= maxThermalLoad and
dataDownlinked_Mb >= 0.8 \* dataVolume_Mb
) {
assign feasible := true;
} else {
assign feasible := false;
}
}
*// ===========================================================================*
*// COMPOSITE ACTION*
*// ===========================================================================*
*// This is the \*main action\* you will:*
*// - sweep in a DOE*
*// - optimize in MDAO*
*// - connect to SPDM execution later*
*// ===========================================================================*
action def PlanPerihelionScienceCampaign {
doc
/\* Plans and evaluates a perihelion science campaign for Parker Solar Probe.
\*
\* This action is intentionally parameterized so it can be:
\* - executed repeatedly
\* - driven by MDAO
\*/
*// -----------------------------------------------------------------------*
*// INPUT PARAMETERS (Design variables / knobs)*
*// -----------------------------------------------------------------------*
*// Solar distance during campaign – drives thermal constraints*
in attribute perihelion_AU : Real;
*// Length of the science campaign window*
in attribute campaignDuration_hr : Real;
*// Instrument duty cycle (fraction of time active)*
in attribute instrumentDutyCycle : Real;
*// Sampling cadence (seconds between samples)*
in attribute cadence_s : Real;
*// Communications downlink rate*
in attribute downlinkRate_Mbps : Real;
*// Available ground contact time*
in attribute contactTime_hr : Real;
*// Spacecraft attitude configuration*
in attribute attitudeMode : String;
*// -----------------------------------------------------------------------*
*// LIMITS / CONSTRAINTS*
*// These could be fixed or also treated as design variables later.*
*// -----------------------------------------------------------------------*
*// Maximum allowable average power draw*
in attribute maxAvgPower_W : Real default 200;
*// Maximum allowable thermal load (normalized)*
in attribute maxThermalLoad : Real default 1.0;
*// -----------------------------------------------------------------------*
*// OUTPUT PARAMETERS (Objectives / constraints)*
*// -----------------------------------------------------------------------*
out item campMetrics : CampaignMetrics;
*// // Scalar objective to maximize*
*// out attribute scienceScore : Real;*
*// // Total data volume produced*
*// out attribute dataVolume_Mb : Real;*
*// // Feasibility flag (used as hard constraint)*
*// out attribute feasible : Boolean;*
*// -----------------------------------------------------------------------*
*// LOCAL VARIABLES (referential features)*
*// Think of these as local variables in a function.*
*// -----------------------------------------------------------------------*
*// -----------------------------------------------------------------------*
*// ACTION FLOW (Lesson 17 constructs)*
*// -----------------------------------------------------------------------*
*// Start of the action*
first start;
*// STEP 1: Configure instruments*
*// Computes power draw and science data rate*
then action cfg : ConfigureInstruments {
in attribute :>> instrumentDutyCycle;
in attribute :>> cadence_s;
in attribute :>> attitudeMode;
}
bind cfg.attitudeMode = attitudeMode;
bind cfg.cadence_s = cadence_s;
bind cfg.instrumentDutyCycle = instrumentDutyCycle;
flow cfg.dataRate_Mbps to dataVol.dataRate_Mbps;
flow cfg.avgPower_W to scoreCampaign.avgPower_W;
flow cfg.avgPower_W to finalCheck.avgPower_W;
*// STEP 2: Estimate thermal load at perihelion*
then action therm : EstimateThermalLoad {
in attribute :>> perihelion_AU;
in attribute :>> attitudeMode;
}
bind therm.perihelion_AU = perihelion_AU;
bind therm.attitudeMode = attitudeMode;
flow therm.peakThermalLoad to scoreCampaign.peakThermalLoad;
flow therm.peakThermalLoad to finalCheck.peakThermalLoad;
*// STEP 3: Compute total data produced*
*// (data rate × duration × seconds/hour ÷ bits/byte)*
then action dataVol : ComputeTotalDataVolume {
in attribute :>> dataRate_Mbps;
in attribute :>> campaignDuration_hr;
}
bind dataVol.campaignDuration_hr = campaignDuration_hr;
flow dataVol.dataVolume_Mb to scoreCampaign.dataVolume_Mb;
flow dataVol.dataVolume_Mb to finalCheck.dataVolume_Mb;
*// STEP 4: Parallel evaluation*
*// - one branch scores the science*
*// - one branch checks downlink feasibility*
then fork;
*// -----------------------------*
*// Branch A: Science scoring*
*// -----------------------------*
then scoreCampaign;
*// -----------------------------*
*// Branch B: Downlink planning*
*// -----------------------------*
then scheduleDownlink;
action scoreCampaign : scoreScienceCampaign {
*// If power and thermal limits are respected,*
*// compute a weighted science score*
in attribute :>> maxAvgPower_W;
in attribute :>> maxThermalLoad;
in attribute :>> avgPower_W;
in attribute :>> peakThermalLoad;
in attribute :>> dataVolume_Mb;
*// Scalar objective to maximize*
out attribute :>> scienceScore;
bind maxAvgPower_W = maxAvgPower_W;
bind maxThermalLoad = maxThermalLoad;
}
then j;
action scheduleDownlink : PlanDownlink {
in attribute :>> downlinkRate_Mbps;
in attribute :>> contactTime_hr;
bind downlinkRate_Mbps = downlinkRate_Mbps;
bind contactTime_hr = contactTime_hr;
}
then j;
*// Synchronize parallel branches*
join j;
*// STEP 5: Final feasibility check*
*// Used as a hard constraint in MDAO*
then action finalCheck : FinalFeasibilityCheck {
in attribute :>> maxAvgPower_W;
in attribute :>> maxThermalLoad;
in attribute :>> dataDownlinked_Mb;
in attribute :>> dataVolume_Mb;
in attribute :>> avgPower_W;
in attribute :>> peakThermalLoad;
out attribute :>> feasible;
bind maxAvgPower_W = maxAvgPower_W;
bind maxThermalLoad = maxThermalLoad;
}
flow scheduleDownlink.dataDownlinked_Mb to finalCheck.dataDownlinked_Mb;
flow finalCheck.feasible to campMetrics.feasible;
flow cfg.avgPower_W to campMetrics.avgPower_W;
flow therm.peakThermalLoad to campMetrics.peakThermalLoad;
flow dataVol.dataVolume_Mb to campMetrics.dataVolume_Mb;
flow scoreCampaign.scienceScore to campMetrics.scienceScore;
}
}