UserDefinedContinuousExplicitDynamicSystem.java

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

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.mklab.nfc.matrix.ComplexNumericalMatrix;
import org.mklab.nfc.matrix.RealNumericalMatrix;
import org.mklab.nfc.ode.SolverStopException;
import org.mklab.nfc.scalar.ComplexNumericalScalar;
import org.mklab.nfc.scalar.RealNumericalScalar;


/**
 * ユーザ定義連続時間動的システムを表わすクラスです。
 * 
 * @author koga
 * @version $Revision: 1.14 $, 2007/07/16
 * @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 UserDefinedContinuousExplicitDynamicSystem<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 UserDefinedContinuousDynamicSystem<RS,RM,CS,CM> implements ContinuousExplicitDynamicSystem<RS,RM,CS,CM> {
  /** M行列 */
  private RM matrixM;
  
  /** システムのM行列を定義したメソッド */
  private Method matrixMFunction;

  /** システムのヤコビ行列を定義したメソッド */
  private Method jacobianMatrixFunction;
  
  /** 微分代数方程式で表せるシステムならばtrue */
  private boolean isDifferentialAlgebraicSystem = false;
  
  /** ヤコビ行列を持っていればtrue */
  private boolean hasJacobianMatrix = false;
  /** 状態と状態の微分の初期値が整合していればtrue */
  private boolean hasConsistentInitialValue = false;

  /**
   * 新しく生成された<code>UserDefinedDynamicSystem</code>オブジェクトを初期化します。
   * 
   * @param obj 呼び出し対象オブジェクト。nullの場合は静的メソッドを参照します
   * @param sunit unit of scalar
   */
  public UserDefinedContinuousExplicitDynamicSystem(Object obj, RS sunit) {
    super(obj, sunit);
    this.matrixM = sunit.createUnitGrid(getStateSize());
  }

  /**
   * 新しく生成された<code>UserDefinedContinuousDynamicSystem</code>オブジェクトを初期化します。
   * @param sunit unit of scalar
   */
  public UserDefinedContinuousExplicitDynamicSystem(RS sunit) {
    this(null, sunit);
  }
  
  /**
   * {@inheritDoc}
   */
  @Override
  public RM matrixM() throws SolverStopException {
    try {
      return (RM)this.matrixMFunction.invoke(this.object);
    } catch (IllegalArgumentException e) {
      throw new SolverStopException(e);
    } catch (IllegalAccessException e) {
      throw new SolverStopException(e);
    } catch (InvocationTargetException e) {
      throw new SolverStopException(e.getTargetException());
    } catch (Exception e) {
      throw new SolverStopException(e);
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public RM stateEquation(RS t, RM x, RM u) throws SolverStopException {
    try {
      return (RM)this.stateFunction.invoke(this.object, t, x, u);
    } catch (IllegalArgumentException e) {
      throw new SolverStopException(e);
    } catch (IllegalAccessException e) {
      throw new SolverStopException(e);
    } catch (InvocationTargetException e) {
      throw new SolverStopException(e.getTargetException());
    } catch (Exception e) {
      throw new SolverStopException(e);
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public RM getJacobianMatrix(RS t, RM x, RM u) {
    try {
      return (RM)this.jacobianMatrixFunction.invoke(this.object, t, x, u);
    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * M行列を定義したメソッドを設定します。
   * 
   * @param method M行列を定義したメソッド
   * @throws SecurityException メソッドにアクセスする権利が無い場合
   */
  public void setMatrixMFunction(final Method method) throws SecurityException {
    this.matrixMFunction = method;
    this.matrixMFunction.setAccessible(true);
  }
  
  /**
   * ヤコビ行列を定義したメソッドを設定します。
   * 
   * @param method ヤコビ行列を定義したメソッド
   * @throws SecurityException メソッドにアクセスする権利が無い場合
   */
  public void setJacobianMatrixFunction(final Method method) throws SecurityException {
    this.jacobianMatrixFunction = method;
    this.jacobianMatrixFunction.setAccessible(true);
  }

  /**
   * {@inheritDoc}
   */
  public RM differentialEquation(RS t, RM x, RM inputOutput) throws SolverStopException {
    final RM u = inputOutput.getRowVectors(1, getInputSize());
    return stateEquation(t, x, u);    
  }
  
  /**
   * Mx'=f(t,x,u)のM行列を設定します。
   * @param matrixM M行列
   */
  public void setMatrixM(RM matrixM) {
    this.matrixM = matrixM;
  }
  
  /**
   * {@inheritDoc}
   */
  public RM getMatrixM() {
    return this.matrixM;
  }

  /**
   * {@inheritDoc}
   */
  public boolean isDifferentialAlgebraicSystem() {
    return this.isDifferentialAlgebraicSystem;
  }

  /**
   * {@inheritDoc}
   */
  public boolean hasJacobianMatrix() {
    return this.hasJacobianMatrix;
  }

  /**
   * {@inheritDoc}
   */
  public boolean hasConsistentInitialValue() {
    return this.hasConsistentInitialValue;
  }
  
  /**
   * 状態と状態の微分の初期値が整合するか設定します。
   * @param hasConsistentInitialValue 状態と状態の微分の初期値が整合すればtrue
   */
  public void setHasConsistentInitialValue(boolean hasConsistentInitialValue) {
    this.hasConsistentInitialValue = hasConsistentInitialValue;
  }

  /**
   * ヤコビ行列を持っているか設定します。
   * @param hasJacobianMatrix ヤコビ行列をもっていればtrue
   */
  public void setHasJacobianMatrix(boolean hasJacobianMatrix) {
    this.hasJacobianMatrix = hasJacobianMatrix;
  }
}