DoubleBlockSampledDataSystem.java

/**
 * $Id$
 *
 * Copyright (C) 2004-2005 Koga Laboratory. All rights reserved.
 */

package org.mklab.tool.control.system.sampled;

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

import org.mklab.nfc.matrix.DoubleMatrix;
import org.mklab.nfc.ode.SolverStopException;
import org.mklab.tool.control.system.DoubleDynamicSystem;
import org.mklab.tool.control.system.DoubleLinearSystemOperator;
import org.mklab.tool.control.system.DoubleStaticSystem;
import org.mklab.tool.control.system.DoubleSystemOperator;
import org.mklab.tool.control.system.continuous.DoubleContinuousExplicitDynamicSystem;
import org.mklab.tool.control.system.continuous.DoubleContinuousLinearDynamicSystem;
import org.mklab.tool.control.system.discrete.DoubleDiscreteLinearDynamicSystem;


/**
 * サンプル値システムのブロックシステムを表わすクラスです。
 * 
 * @author koga
 * @version $Revision$
 */
public abstract class DoubleBlockSampledDataSystem extends DoubleBlockSamplingSystem {

  /** 連続時間動的システムのリスト */
  protected List<DoubleContinuousExplicitDynamicSystem> continuousDynamicSystems = new ArrayList<>();

  /**
   * 新しく生成された<code>BlockSampledDataSystem</code>オブジェクトを初期化します。
   * 
   * @param elements 隣接行列
   * @param inputNodes 入力ノードの番号のリスト(番号は1から始まる)
   * @param outputNodes 出力ノードの番号のリスト(番号は1から始まる)
   */
  public DoubleBlockSampledDataSystem(final DoubleSystemOperator[][] elements, final List<Integer> inputNodes, final List<Integer> outputNodes) {
    super(elements, inputNodes, outputNodes);
    setupContinuousDynamicSystemList();
    separateDirectFeedthroughAndNonDirectFeedthrough();
  }

  /**
   * 連続時間動的システムのリストを設定します。
   */
  private void setupContinuousDynamicSystemList() {
    this.continuousDynamicSystems.clear();

    final int size = getNodeSize();

    for (int row = 0; row < size; row++) {
      for (int column = 0; column < size; column++) {
        final DoubleSystemOperator system = getSystemOperator(row, column);
        if (system instanceof DoubleContinuousExplicitDynamicSystem) {
          this.continuousDynamicSystems.add((DoubleContinuousExplicitDynamicSystem)system);
        }
      }
    }
  }

  /**
   * ノードの値を計算します。
   * 
   * @param t 時間
   * @throws SolverStopException ソルバーが停止された場合
   */
  protected void calcNodeValue(final double t) throws SolverStopException {
    this.time = t;
    calcNodeValue();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected DoubleMatrix calcOutputOfDirectFeedthroughSystem(final DoubleSystemOperator system, final DoubleMatrix u) throws SolverStopException {
    if (system instanceof DoubleDynamicSystem) {
      DoubleDynamicSystem dSystem = (DoubleDynamicSystem)system;
      return dSystem.outputEquation(this.time, dSystem.getState(), u);
    }

    if (system instanceof DoubleStaticSystem) {
      return ((DoubleStaticSystem)system).outputEquation(this.time, u);
    }

    throw new RuntimeException(Messages.getString("BlockSampledDataSystem.0")); //$NON-NLS-1$
  }

  /**
   * @see org.mklab.tool.control.system.BlockSystem#calcOutputOfNonDirectFeedthroughSystem(org.mklab.tool.control.system.SystemOperator)
   */
  @Override
  protected DoubleMatrix calcOutputOfNonDirectFeedthroughSystem(final DoubleSystemOperator system) throws SolverStopException {
    if (system instanceof DoubleDynamicSystem) {
      DoubleDynamicSystem dSystem = (DoubleDynamicSystem)system;
      return dSystem.outputEquation(this.time, dSystem.getState());
    }

    if (system instanceof DoubleStaticSystem) {
      return ((DoubleStaticSystem)system).outputEquation(this.time);
    }

    throw new RuntimeException(Messages.getString("BlockSampledDataSystem.1")); //$NON-NLS-1$
  }

  /**
   * @see org.mklab.tool.control.system.BlockSystem#createStrictlyProperLinearDynamicSystem(org.mklab.tool.control.system.SystemOperator)
   */
  @Override
  protected DoubleSystemOperator createStrictlyProperLinearDynamicSystem(final DoubleSystemOperator system) {
    final DoubleMatrix a = ((DoubleLinearSystemOperator)system).getLinearSystem().getA();
    final DoubleMatrix b = ((DoubleLinearSystemOperator)system).getLinearSystem().getB();
    final DoubleMatrix c = ((DoubleLinearSystemOperator)system).getLinearSystem().getC();

    if (system instanceof DoubleContinuousExplicitDynamicSystem) {
      final DoubleContinuousLinearDynamicSystem newSystem = new DoubleContinuousLinearDynamicSystem(a, b, c);
      newSystem.setInitialState(((DoubleContinuousLinearDynamicSystem)system).getInitialState());
      return newSystem;
    }

    final DoubleDiscreteLinearDynamicSystem newSystem = new DoubleDiscreteLinearDynamicSystem(a, b, c);
    newSystem.setSamplingInterval(((DoubleDiscreteLinearDynamicSystem)system).getSamplingInterval());
    newSystem.setAtSamplingPoint(((DoubleDiscreteLinearDynamicSystem)system).isAtSamplingPoint());
    newSystem.setInitialState(((DoubleDiscreteLinearDynamicSystem)system).getInitialState());
    return newSystem;
  }

  /**
   * @see org.mklab.tool.control.system.BlockSystem#replaceDynamicSystemList(org.mklab.tool.control.system.SystemOperator, org.mklab.tool.control.system.SystemOperator)
   */
  @Override
  protected boolean replaceDynamicSystemList(final DoubleSystemOperator oldSystem, final DoubleSystemOperator newSystem) {
    if (super.replaceDynamicSystemList(oldSystem, newSystem)) {
      return true;
    }

    if (oldSystem instanceof DoubleContinuousExplicitDynamicSystem) {
      final int index = this.continuousDynamicSystems.indexOf((DoubleContinuousExplicitDynamicSystem)oldSystem);
      if (index == -1) {
        return false;
      }
      this.continuousDynamicSystems.set(index, (DoubleContinuousExplicitDynamicSystem)newSystem);
      return true;
    }

    return false;
  }
}