#include "usercm1.h"
#include <math.h>

static USERCM1 uso(true);

USERCM1::USERCM1(bool bRegister) :
  ContactModel(ulModelCM1, bRegister),
            kn(0.0), ks(0.0), fric(0.0) {
  SetDelete(true);
}


const char *USERCM1::Name(void) const {
  return("usercm1");
}


const char **USERCM1::PropNames(void) const {
  static const char *strKey[] = {
    "cm1_kn", "cm1_ks", "cm1_fric",
     0
  };
  return(strKey);
}


double USERCM1::ReturnProp(int n) const {
  switch (n) {
    case 0:  return kn;
    case 1:  return ks;
    case 2:  return fric;
    default: return 0.0;
  }
}


void USERCM1::AcceptProp(int n, double v) {
  switch (n) {
    case 0: kn   = v; break;
    case 1: ks   = v; break;
    case 2: fric = v; break;
    default:          break;
  }
}


//------------ user-defined contact model "cm1" -----------
void USERCM1::FDlaw(FdBlock& fb, char cDim) {
  if (cDim==2) { // 2D Section
    if (fb.u_n > 0.0) {
      fb.n_force  =  kn * fb.u_n;
      fb.s_force -=  ks * fb.u_dot_s * fb.tdel;
      double max_s_force = fb.n_force * fric;
      if (fabs(fb.s_force) > max_s_force) {
        fb.s_force = fb.s_force < 0.0 ? -fabs(max_s_force) : fabs(max_s_force);
        fb.bSliding = true;
      }
      fb.knest = kn;
      fb.ksest = ks;
      fb.skip  = false;
    }
    else {
      fb.n_force = 0.0;
      fb.s_force = 0.0;
      fb.knest = 0.0;
      fb.ksest = 0.0;
      fb.skip  = true;
    }
  }
  else { // ... 3D section ...
    if (fb.u_n > 0.0) {
      fb.n_force =  kn * fb.u_n;
      double kst = ks * fb.tdel;
      UMdvect vec = fb_u_dot_s * kst;
      fb_s_force= fb_s_force- vec;
      double max_s_force = fb.n_force * fric; // Slip check
      double dX = fb.pts_force->x;
      double dY = fb.pts_force->y;
      double dZ = fb.pts_force->z;
      double sfmag = sqrt(dX*dX + dY*dY + dZ*dZ);
      if (sfmag > max_s_force) {
        double rat = max_s_force / sfmag;
        fb_s_force= fb_s_force* rat;
        fb.bSliding = true;
      }
      fb.knest = kn;
      fb.ksest = ks;
      fb.skip  = false;
    }
    else {
      fb.n_force = 0.0;
      fb_s_force.Fill(0.0);
      fb.knest = 0.0;
      fb.ksest = 0.0;
      fb.skip  = true;
    }
  }
}


const char *USERCM1::SaveRestore(ModelSaveObject *mso) {
  const char *str = ContactModel::SaveRestore(mso);
  if (str) return(str);
  mso->Initialize(3,0,1);
  mso->Save( 0, delete_flag);
  mso->Save( 0, kn);
  mso->Save( 1, ks);
  mso->Save( 2, fric);
  return(0);
}



/* EoF */

