Main Content

Analysis Function Constructs

Analyze architectures to choose between design alternatives or improve existing designs. You can use analysis functions with System Composer™ architecture models to perform systems analysis and trade studies.

An analysis function is a MATLAB® function that computes values necessary to evaluate the architecture using the properties of each element in the model instance.

Use an analysis function to calculate the result of an analysis and determine the optimal parameters to use for behavior models to simulate the architectural system.

For more information on analysis functions and architecture instances, see Analyze Architecture.

Roll-Up Analysis for Quadcopter Design

Use a roll-up analysis function to calculate a total or average of model element property values. Assign properties to model elements using stereotypes. For more information, see Define Profiles and Stereotypes.

In this example, the analysis function systemWithProps_1calculates the total cost of all components in the model and is compatible with the Analysis Viewer tool.

function systemWithProps_1(instance,varargin)

if instance.isComponent() && ~isempty(instance.Components)...
 && instance.hasValue('SystemProfile.PhysicalElement.unitCost')
    sysComponent_unitPrice = 0;
    for child = instance.Components
        if child.hasValue('SystemProfile.PhysicalElement.unitCost')
           comp_price = child.getValue('SystemProfile.PhysicalElement.unitCost');
           sysComponent_unitPrice = sysComponent_unitPrice + comp_price;

This analysis function iterates through an architecture instance. First, the sysComponent_unitPrice variable is set to zero so that every time the analysis is run, sums do not accumulate indefinitely. Each component instance is checked for a unitCost property value. All unitCost property values are summed up and saved in the sysComponent_unitPrice variable. Finally, the unitCost property of the current component instance is updated with the value of sysComponent_unitPrice. For more information, see Write Analysis Function.

In this example, a section of the analysis function calculateEndurance calculates endurance for a quadcopter using component instance properties. The calculated endurance value is then set for the architecture instance of the quadcopter with the setValue function.

if payloadBatteryCapacity == 0
      totalPower = powerConsumption + hoverPower/efficiency;
      endurance = (batteryCapacity/1000)/(totalPower/voltage)*60;
      payloadEndurance = (payloadBatteryCapacity/1000)/(powerConsumption/voltage)*60;
      flightEndurance = (batteryCapacity/1000)/((hoverPower/efficiency)/voltage)*60;
      if flightEndurance < payloadEndurance
            endurance = flightEndurance;
            endurance = payloadEndurance;
            warning('Endurance is limited by payload electronics.')

For more information and for the supporting files, see Calculate Endurance Using Quadcopter Architectural Design.

Class-Based Analysis for Battery Sizing

Use MATLAB classes for an analysis function to iterate over an object, or instantiation of the class.

In this example, the class called computeBatterySizing involves properties and methods useful for the analysis function computeLoad.

classdef computeBatterySizing < handle


        function obj = computeBatterySizing(obj)
            obj.totalCrankingInrushCurrent = 0;
            obj.totalCrankingCurrent = 0;            
            obj.totalAccesoriesCurrent = 0;
            obj.totalKeyOffLoad = 0;
            obj.batteryCCA = 0;
            obj.batteryCapacity = 0;
            obj.puekertcoefficient = 1.2;
        function obj = displayResults(obj)
            tempNumdaysToDischarge = (((obj.batteryCapacity/obj.puekertcoefficient)*0.3)/(obj.totalKeyOffLoad*1e-3))/24;
            disp("Total KeyOffLoad: " + num2str(obj.totalKeyOffLoad) + " mA");
            disp("Number of days required for KeyOffLoad to discharge 30% of battery: " + ...
                 num2str(tempNumdaysToDischarge) + ".");
            disp("Total CrankingInRush current: " + num2str(obj.totalCrankingInrushCurrent) + " A");
            disp("Total Cranking current: " + num2str(obj.totalCrankingCurrent) + " A");
            if(obj.totalCrankingCurrent > obj.batteryCCA) 
                disp("The Cold Cranking Amps of the specified battery is not sufficient to start the car 0 F.")   
                disp("CCA of the specified battery is sufficient to start the car at 0 F.")    

For more information and for the supporting files, see Battery Sizing and Automotive Electrical System Analysis.

Allocation-Based Analysis for Tire Pressure Monitoring

A functional-to-logical allocation matrix allocates components in a functional architecture to components in a logical architecture. Coverage analysis is the most basic form of analysis to determine whether all elements have been allocated.

First, open the project for this example. Then, load the allocation set and collect the scenarios.

allocSet = systemcomposer.allocation.load('FunctionalAllocation');
  scenario = allocSet.Scenarios;

Verify that each function in the system is allocated.

import systemcomposer.query.*;
  [~, allFunctions] = allocSet.SourceModel.find(HasStereotype(IsStereotypeDerivedFrom("TPMSProfile.Function")));
  unAllocatedFunctions = [];
  for i = 1:numel(allFunctions)
      if isempty(scenario.getAllocatedTo(allFunctions(i)))
          unAllocatedFunctions = [unAllocatedFunctions allFunctions(i)];

  if isempty(unAllocatedFunctions)
      fprintf('All functions are allocated');
      fprintf('%d Functions have not been allocated', numel(unAllocatedFunctions));
All functions are allocated

The output verifies that all functions are allocated.

For more information and for the supporting files, see Allocate Architectures in Tire Pressure Monitoring System.

Remaining Useful Life Analysis for Mobile Robot Design

Remaining useful life (RUL) analysis estimates the time remaining before different subsystems fail. The goal is to anticipate maintenance and thus minimize system disruptions.

In this example, the analysis function scMobileRobotAnalysis is compatible with the Analysis Viewer tool.

function scMobileRobotAnalysis(instance,varargin)
    ExpectedYearsBeforeFirstMaintenance = 2; 
    if ~instance.isArchitecture() 
        if instance.hasValue("HardwareBaseStereotype.Life")
            Life = instance.getValue("HardwareBaseStereotype.Life");
            UsagePerDay = instance.getValue("HardwareBaseStereotype.UsagePerDay");
            UsagePerYear = instance.getValue("HardwareBaseStereotype.UsagePerYear");
            WillSurvive = Life > UsagePerDay * UsagePerYear * ExpectedYearsBeforeFirstMaintenance; 
            instance.setValue("HardwareBaseStereotype.ExceedExpectedMaintenance", WillSurvive);

After running this analysis function, you can optimize the desired first expected maintenance time in years. Each component that exceeds the expected maintenance time, in this case set to two years, is flagged with a check box. Unchecked components should be optimized or replaced with longer-lasting parts.

For more information and for the supporting files, see Define Stereotypes and Perform Analysis.

Variant Analysis for Insulin Infusion Pump Design

Use variant analysis to choose one optimal combination of variants by comparing them with a calculated metric.

In this example, the analysis function OutcomeAnalysis is used to determine the best configuration for an insulin infusion pump. This standalone analysis function does not involve the Analysis Viewer tool. Instead, the analysis function uses the iterate function and can be executed directly from the MATLAB Command Window.

The OutcomeAnalysis function first gathers all variant choice components named Pump and BGSensor.

function outcomes = OutcomeAnalysis()

modelname = 'InsulinInfusionPumpSystem';

therapyModel = systemcomposer.openModel(modelname);
components = therapyModel.Architecture.Components;
for idx = 1:numel(components)
    if strcmp(components(idx).Name,'Pump')
        pumps = components(idx).getChoices;
        pumpNames = {};
        for jdx = 1:numel(pumps)
            pumpNames{end+1} = pumps(jdx).Name;
    elseif strcmp(components(idx).Name,'BGSensor')
        sensors = components(idx).getChoices;
        sensorNames = {};
        for jdx = 1:numel(sensors)
            sensorNames{end+1} = sensors(jdx).Name;

The analysis function then collects all variant combinations to iterate over.

config.Sensor = sensorNames{1};
config.Pump = pumpNames{1};
configs = {};

for idx = 1:numel(sensorNames)
    for jdx = 1:numel(pumpNames)
        config.Sensor = sensorNames{idx};
        config.Pump = pumpNames{jdx};
        configs{end+1} = config;

The analysis function activates the variants one by one, iterates over the model properties, and collects outcomes. To set variant combinations, OutcomeAnalysis uses the setVariants function. To compute the outcomes, OutcomeAnalysis uses the computeOutcome function.

outcomes = {};

for idx = 1:numel(configs)
    hOutcome = OutcomeContainer(configs{idx});
    hOutcome.setWeights([1e-6 1 10 1 1000]');
    outcomes{end+1} = hOutcome;

Finally, the analysis function plots the net outcome to reveal the optimal design choice.

properties = {'Lower NRE','Higher Accuracy','Better Compliance',...
'Sooner To Market','Lower Operating Cost'};
plotMatrix = zeros(numel(outcomes), numel(properties));
plotStrings = {};
for idx = 1:numel(outcomes)
    plotStrings{idx} = [outcomes{idx}.Sensor '+' outcomes{idx}.Pump];
    plotMatrix(idx,1) = 1/(outcomes{idx}.NRE);
    plotMatrix(idx,2) = outcomes{idx}.Accuracy;
    plotMatrix(idx,3) = outcomes{idx}.Compliance;
    plotMatrix(idx,4) = 1/(outcomes{idx}.TimeToMarket);
    plotMatrix(idx,5) = 1/(outcomes{idx}.AnnualCost);

colmin = zeros(1,5);
colmax = max(plotMatrix);
normalizedMatrix = rescale(plotMatrix,'InputMin',colmin,'InputMax',colmax);

if exist('spider_plot') == 2
    fig = figure;

    title(sprintf('Trade Study Outcome'),...
        'FontSize', 14);
    legend(plotStrings, 'Location', 'eastoutside');
    pos = fig.Position;
    pos(2) = pos(2) - pos(4);
    pos(3) = 2*pos(3);
    pos(4) = 2*pos(4);
    fig.Position = pos;
    vals = sum(normalizedMatrix,2)/5;
    x_labels = categorical(plotStrings);
    h = bar(x_labels,vals);
    title('Net outcome');
    ax = h.Parent;
    ax.YLabel.String = 'Normalized units';

For more information and for the supporting files, see Design Insulin Infusion Pump Using Model-Based Systems Engineering.

See Also

| | | | | | | | | | |

Related Topics