BlockPiecewiseContinuousStaticSystem.java

/*
 * Created on 2007/04/08
 * Copyright (C) 2007 Koga Laboratory. All rights reserved.
 *
 */
package org.mklab.tool.control.system.continuous;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.ode.PiecewiseContinuousAlgebraicSystem;
import org.mklab.nfc.ode.SolverStopException;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;
import org.mklab.tool.control.system.SystemOperator;


/**
 * 区分的連続な代数方程式で表現されるブロック連続時間静的システムを表わすクラスです。
 * 
 * @author koga
 * @version $Revision: 1.13 $, 2007/04/08
  * @param <RS> type of real scalar
 * @param <RM> type of real matrix
 * @param <CS> type of complex scalar
 * @param <CM> type of complex matrix
*/
public class BlockPiecewiseContinuousStaticSystem<RS extends RealNumericalScalar<RS, RM, CS, CM>, RM extends RealNumericalMatrix<RS, RM, CS, CM>, CS extends ComplexNumericalScalar<RS, RM, CS, CM>, CM extends ComplexNumericalMatrix<RS, RM, CS, CM>> extends BlockContinuousStaticSystem<RS,RM,CS,CM> implements PiecewiseContinuousAlgebraicSystem<RS,RM,CS,CM> {

  /** 区分的連続代数システムのリスト */
  private List<PiecewiseContinuousAlgebraicSystem<RS,RM,CS,CM>> piecewiseContinuousSystems = new ArrayList<>();

  /**
   * 新しく生成された<code>BlockPiecewiseContinuousStaticSystem</code>オブジェクトを初期化します。
   * 
   * @param elements 隣接行列
   * @param inputNodes 入力ノード番号のリスト(番号は1から始まります)
   * @param outputNodes 出力ノード番号のリスト(番号は1から始まります)
   * @param sunit unit of scalar
   */
  public BlockPiecewiseContinuousStaticSystem(SystemOperator<RS, RM, CS, CM>[][] elements, List<Integer> inputNodes, List<Integer> outputNodes, RS sunit) {
    super(elements, inputNodes, outputNodes, sunit);
    setupPiecewiseContinuousSystems();
  }

  /**
   * {@inheritDoc}
   */
  public RS getDiscontinuousPoint(final RS t1,  final RM input1, final RS t2,  final RM input2) throws SolverStopException {
    outputEquation(t1);
    final List<RM> inputs1 = getInputs();

    outputEquation(t2);
    final List<RM> inputs2 = getInputs();

    final List<RS> points = getDiscontinuousPoints(t1, inputs1, t2, inputs2);

    outputEquation(t1);

    final RS[] sortedPoints = points.toArray(this.sunit.createArray(points.size()));
    Arrays.sort(sortedPoints);

    return sortedPoints[0];
  }

  /**
   * 区分的連続代数システムへの入力を返します。
   * 
   * @return 区分的連続代数システムへの入力
   */
  private List<RM> getInputs() {
    final List<RM> inputs = new ArrayList<>();
    for (PiecewiseContinuousAlgebraicSystem<RS,RM,CS,CM> system : this.piecewiseContinuousSystems) {
      inputs.add(getInputNodeValueOf((SystemOperator<RS,RM,CS,CM>)system).createClone());
    }
    return inputs;
  }

  /**
   * 指定された区間内([(t1,inputs1),(t2,inputs2)]の不連続点の時刻を返します。
   * 
   * @param t1 不連続点の前の時刻
   * @param inputs1 不連続点の前の入力
   * @param t2 不連続点の後の時刻
   * @param inputs2 不連続点の後の入力
   * @return 指定された区間内([(t1,inputs1),(t2,inputs2)]の不連続点の時刻
   * @exception SolverStopException ソルバーが停止された場合
   */
  private List<RS> getDiscontinuousPoints(final RS t1, final List<RM> inputs1, final RS t2, final List<RM> inputs2) throws SolverStopException {
    final List<RS> points = new ArrayList<>();
    for (int i = 0; i < this.piecewiseContinuousSystems.size(); i++) {
      final PiecewiseContinuousAlgebraicSystem<RS,RM,CS,CM> system = this.piecewiseContinuousSystems.get(i);
      final RM u1 = inputs1.get(i);
      final RM u2 = inputs2.get(i);
      points.add(system.getDiscontinuousPoint(t1, u1, t2, u2));
    }
    return points;
  }

  /**
   * {@inheritDoc}
   */
  public List<Integer> getPiece(final RS t,  final RM u) throws SolverStopException {
    calcNodeValue(t);

    final List<Integer> pieces = new ArrayList<>();
    for (PiecewiseContinuousAlgebraicSystem<RS,RM,CS,CM> system : this.piecewiseContinuousSystems) {
      pieces.addAll(system.getPiece(t, getInputNodeValueOf((SystemOperator<RS,RM,CS,CM>)system)));
    }

    return pieces;
  }

  /**
   * 区分的連続システムのリストを設定します。
   */
  private void setupPiecewiseContinuousSystems() {
    this.piecewiseContinuousSystems.clear();

    final int size = getNodeSize();

    for (int row = 0; row < size; row++) {
      for (int column = 0; column < size; column++) {
        final SystemOperator<RS,RM,CS,CM> system = getSystemOperator(row, column);
        if (system instanceof PiecewiseContinuousAlgebraicSystem) {
          this.piecewiseContinuousSystems.add((PiecewiseContinuousAlgebraicSystem<RS,RM,CS,CM>)system);
        }
      }
    }
  }
}