/* Fesslix - Stochastic Analysis
 * Copyright (C) 2010-2014 Wolfgang Betz
 *
 * Fesslix is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Fesslix is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Fesslix.  If not, see <http://www.gnu.org/licenses/>. 
 */

#ifndef fesslix_flxdyna_kernel_H
#define fesslix_flxdyna_kernel_H

#include "flxlibs_interface.h"


class flxDynaProj {
  private:
    const tuint Ndof;
    const tuint Nt;
    tdouble dt;
    FlxMtx_baseS* M;	// mass matrix
    FlxMtx_baseS* K;	// stiffness matrix
    FlxMtx_baseS* D;	// damping matrix
    // required by the solver
      FlxMtx_baseS* C0;	// help matrix
      FlxMtxLTriBand* L0; // help matrix 2
      FlxMtxLTri* Ltri;
      flxVec hv;		// help vector (Ndof)
    FlxMtx x;		// displacement 	(Nt+1)*Ndof	(output)
    FlxMtx v;		// velocity 		(Nt+1)*Ndof	(output)
    FlxMtx a;		// acceleration 	(Nt+1)*Ndof	(output)
    FlxMtx f;		// force @ time-step    Nt*Ndof	(input)
    // initial conditions
      flxVec x0;
      flxVec v0;
      flxVec a0;
    const std::string name;
    // for the eigenmodes
      bool emode_valid;
      flxVec* Eigenvalues;			// natural frequencies (Ndof)
      std::vector<flxVec> Eigenvectors;	// Eigenvectors (Ndof*Ndof)
    
    void solve_prepare();
    void solve_modes();
  public:
    flxDynaProj(const std::string name, const tuint Ndof, const tuint Nt);
    ~flxDynaProj();
    
    const tuint get_Ndof() const { return Ndof; }
    const tuint get_Nt() const { return Nt; }
    const tdouble get_dt() const { return dt; }
    void set_dt(const tdouble& dtV);
    void set_x0(const flxVec& x0V) { x0.assign_save(x0V); }
    void set_v0(const flxVec& v0V) { x0.assign_save(v0V); }
    void set_a0(const flxVec& a0V) { x0.assign_save(a0V); }
    void set_M(FlxMtx_baseS* MV);
    void set_K(FlxMtx_baseS* KV);
    void set_D(FlxMtx_baseS* DV);
    void set_dratio(const flxVec& a0V);
    FlxMtx_baseS* get_M(const bool is_modified) { if (is_modified) { emode_valid=false; }; return M; }
    FlxMtx_baseS* get_K(const bool is_modified) { if (is_modified) { emode_valid=false; }; return K; }
    FlxMtx_baseS* get_D() { return D; }
    FlxMtx& get_f() { return f; }
    FlxMtx& get_x() { return x; }
    FlxMtx& get_v() { return v; }
    FlxMtx& get_a() { return a; }
    const tdouble get_natfreq(const tuint mID);	// mID=0...Ndof-1
    
    void solve_x();
    void solve_a();
};

// ------------------------------------------------------------------------------------------------

class flxDynaBox {
  private:
    #if FLX_DEBUG
      /**
      * @brief number of instances of this class - only one class may exist
      */
      static int Cinst;
    #endif
    std::map<std::string, flxDynaProj*> box;
  public:
    flxDynaBox();
    ~flxDynaBox();
    
    void insert (const std::string name, const tuint Ndof, const tuint Nt);
    flxDynaProj& get ( const std::string& name );
};












#endif // fesslix_flxdyna_kernel_H

