/* Fesslix - Stochastic Analysis
 * Copyright (C) 2010-2016 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/>. 
 */

#include "flxfem_element_beam.h"


flxElement_1D_beam::flxElement_1D_beam(flxMaterial* material, flxCrossSec* crossSec, flxEdge& edge)
: flxElement_1D_base(material, crossSec, edge)
{
  DOFvec[0] = edge.find_dof(FlxDof::dof_wx,true);
  DOFvec[1] = edge.find_dof(FlxDof::dof_wy,true);
  DOFvec[2] = edge.find_dof(FlxDof::dof_wz,true);
  DOFvec[3] = edge.find_dof(FlxDof::dof_rx,true);
  DOFvec[4] = edge.find_dof(FlxDof::dof_ry,true);
  DOFvec[5] = edge.find_dof(FlxDof::dof_rz,true);
  // make sure pOrder of edges = 1
    for (tuint i=0;i<6;++i) {
      if (DOFvec[i]->get_DOFpOrder()!=1) {
	throw FlxException("flxElement_1D_beam::flxElement_1D_beam","Order of the ansatz functions on the edge must be 1.");
      }
    }
}

const tdouble flxElement_1D_beam::get_el_info_help(const FlxElementInfo::elInfo eI) const
{
  throw FlxException_NotImplemented("flxElement_1D_beam::get_el_info_help");
}

void flxElement_1D_beam::assembleStf(const tdouble* meshInterval, const tuint meshInterval_size)
{
  // everything is constant !!!
    const tdouble E = material->get_E();
    const tdouble G = material->get_G();
    const tdouble A = crossSec->get_A();
    const tdouble LE = edge.calc_length();
    const tdouble Iy = crossSec->get_Iy();
    const tdouble Iz = crossSec->get_Iz();
    const tdouble It = crossSec->get_It();
    // Schubstarr:
      const tdouble my=ZERO; tdouble mz=ZERO;
    for (tuint i=0;i<meshInterval_size;++i) {
      const tdouble L = LE*(meshInterval[i+1]-meshInterval[i])/2.0;
      const tdouble a0=E*A/L;
      const tdouble ay1=E*Iy/L/(1+my);
      const tdouble ay2=E*Iy*(4+my)/4/L/(1+my);
      const tdouble ay3=E*Iy*(2-my)/2/L/(1+my);
      const tdouble az1=E*Iz/L/(1+mz);
      const tdouble az2=E*Iz*(4+mz)/4/L/(1+mz);
      const tdouble az3=E*Iz*(2-mz)/2/L/(1+mz);
      
      K(0,0,i,a0); K(1,1,i,12*az1/(L*L)); K(2,2,i,12*ay1/(L*L)); K(3,3,i,G*It/L); K(4,4,i,4*ay2); K(5,5,i,4*az2);
      K(6,6,i,a0); K(7,7,i,12*az1/(L*L)); K(8,8,i,12*ay1/(L*L)); K(9,9,i,G*It/L); K(10,10,i,4*ay2); K(11,11,i,4*az2);
      
      K(6,0,i,-ONE*a0);
		      K(9,3,i,-ONE*G*It/L); 
      
      K(4,2,i,-6*ay1/L); 
      K(8,2,i,-12*ay1/(L*L));  K(8,4,i,6*ay1/L);
      K(10,2,i,-6*ay1/L); 	   K(10,4,i,2*ay3);      K(10,8,i,6*ay1/L);
      
      K(5,1,i,-6*az1/L);
      K(7,1,i,-12*az1/(L*L));  K(7,5,i,6*az1/L);
      K(11,1,i,-6*az1/L);	   K(11,5,i,2*az3);     K(11,7,i,6*az1/L);

    }
}

void flxElement_1D_beam::K(const tuint i, const tuint j, const tuint ElIdx, const tdouble &value)
{
  const tuint e1 = (i>=6)?(i-6):i;
  const tuint e2 = (j>=6)?(j-6):j;
  const tuint ni = (i>=6)?1:0;
  const tuint nj = (j>=6)?1:0;
  edge.update_local_StfMtx(ElIdx,DOFvec[e1],ni,DOFvec[e2],nj,value);
}




