#include "cm2model.h"



CM2::CM2(bool bRegister) :
  ContactModel(ulModelCM2, bRegister),
    kn(0.0), ks(0.0), visc(0.0), bond_when_touch(false),
    con1(0.0), con2(0.0), bonded(false) {
}


const char *CM2::Name(void) const {
  return("viscous");
}


const char **CM2::PropNames(void) const {
  static const char *strKey[] = {
  "vis_kn", "vis_ks", "vis_viscosity", "vis_bond_when_touch",
   0
  };
  return(strKey);
}


ContactModel *CM2::Clone(PropBlock *pb) const {
  CM2 *cm_2 = new CM2;
  if(pb) {  
    if (pb->bIsNear) {
      cm_2->bonded = true;
      cm_2->SetDelete(false);
		}
    else {
      cm_2->bonded = false;
      cm_2->SetDelete(true);
		}
  } 
  return(cm_2);
}


double CM2::ReturnProp(int n) const {
  switch (n) {
    case 0:  return kn;
    case 1:  return ks;
    case 2:  return visc;
    case 3:  return bond_when_touch != 0 ? 1.0 : 0.0;
    default: return 0.0;
  }
}


void CM2::AcceptProp(int n, double v) {
  switch (n) {
    case 0: kn   = v; break;
    case 1: ks   = v; break;
    case 2: visc = v; break;
    case 3: bond_when_touch = v != 0.0 ? 1 : 0; break;
    default:          break;
  }
}


//------------ built-in, user-defined contact model "viscous" -----------
void CM2::FDlaw(FdBlock &fb, char cDim) { // Force/displacement law
  if (!bonded && bond_when_touch) {
    if (fb.u_n > 0.0) {
      bonded = true;
      SetDelete(false);
    }
  }
	if (cDim==2) { // ... 2D section ...
    if (bonded) {
      double c1 = fb.tdel * con2;
      double c2 = con1 - c1;
      double c3 = con1 + c1;
      fb.n_force = kn * fb.u_n;
      fb.s_force = (fb.s_force * c2 - fb.u_dot_s * fb.tdel) / c3;
      fb.knest = kn;
      fb.ksest = ks;
      fb.skip  = false;
		}
		else {
      fb.knest = 0.0;
      fb.ksest = 0.0;
      fb.skip  = true;
		}
	}
	else { // ... 3D section ...
    if (bonded) {
      double c1 = fb.tdel * con2;
      double c2 = con1 - c1;
      double c3 = con1 + c1;
      fb.n_force = kn * fb.u_n;
      UMdvect v1 = fb_s_force* c2;
      UMdvect v2 = fb_u_dot_s * fb.tdel;
      UMdvect v3 = v1 - v2;
      fb_s_force= v3 / c3;
      fb.knest = kn;
      fb.ksest = ks;
      fb.skip  = true;
		}
		else {
      fb.knest = 0.0;
      fb.ksest = 0.0;
      fb.skip  = true;
		}
  }
}


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


void CM2::remap(PropBlock &pb) {
  if (pb.bIsNear) {
    bonded = true;
    SetDelete(false);
  }
  else {
    bonded = false;
    SetDelete(true);
  }
}



/* EoF */
