// Print contact law settings for cracks and finalize variables
void CrackSurfaceContact::Output(void)
{
	// allocate memory for custom crack contact laws
	char *p=new char[(numberOfCracks+1)*sizeof(ContactLaw *)];
	crackContactLaw=(ContactLaw **)p;
	
	// Global material contact law (must be set,if not force to frictionless)
	crackContactLawID = MaterialBase::GetContactLawNum(crackContactLawID);
	if(crackContactLawID<0)
		throw CommonException("Crack settings must select a default contact law","CrackSurfaceContact::Output");
	crackContactLaw[0] = (ContactLaw *)theMaterials[crackContactLawID];
	cout << "Default Contact Law: " << crackContactLaw[0]->name << " (number " << (crackContactLawID+1) << ")" << endl;
	if(crackContactLaw[0]->IsImperfectInterface()) hasImperfectInterface=true;
	
	// print other settings
	cout << "Contact Detection: Normal cod < 0 AND normal dv < 0" << endl;
    mpmgrid.OutputContactByDisplacements();
	if(GetMoveOnlySurfaces())
		cout << "Crack Plane Updating: Average of the crack surfaces" << endl;
	else
		cout << "Crack Plane Updating: Use center of mass velocity" << endl;
	if(GetPreventPlaneCrosses())
		cout << "Crack Plane Crosses: surface particles moved back to the current plane" << endl;
	else
		cout << "Crack Plane Crosses: ignored" << endl;
}
// Print contact law settings for cracks and finalize variables
void CrackSurfaceContact::Output(int numberOfCracks)
{
	char hline[200];
	
	// Default contact law
	if(friction<-10.)
	{   ContactLaw=NOCONTACT;
		sprintf(hline,"contacts ignored");
	}
	else if(friction<-.5)
	{   ContactLaw=STICK;
		sprintf(hline,"stick conditions");
	}
	else if(DbleEqual(friction,(double)0.))
	{   ContactLaw=FRICTIONLESS;
		sprintf(hline,"frictionless sliding");
	}
	else if(friction>10.)
	{   ContactLaw=IMPERFECT_INTERFACE;
		if(Dnc<-100.) Dnc=Dn;
		sprintf(hline,"imperfect interface\n     Dnt = %g MPa/mm, Dnc = %g MPa/mm, Dt = %g MPa/mm",
				Dn,Dnc,Dt);
		hasImperfectInterface=TRUE;
	}
	else
	{   ContactLaw=FRICTIONAL;
		sprintf(hline,"frictional with coefficient of friction: %.6f",friction);
	}
	
	// print results
	cout << "Default Contact: " << hline << endl;
#ifdef _VELOCITY_ONLY_
	cout << "Contact Detection: Normal dv < 0" << endl;
#else
	cout << "Contact Detection: Normal cod < 0 AND normal dv < 0" << endl;
    mpmgrid.OutputContactByDisplacements();
#endif
	if(GetMoveOnlySurfaces())
		cout << "Crack Plane Updating: Average of the crack surfaces" << endl;
	else
		cout << "Crack Plane Updating: Use center of mass velocity" << endl;
	if(GetPreventPlaneCrosses())
		cout << "Crack Plane Crosses: surface particles moved back to the current plane" << endl;
	else
		cout << "Crack Plane Crosses: ignored" << endl;
    
	// allocate memory for custom crack contact laws
	char *p=new char[(numberOfCracks+1)*sizeof(ContactDetails)];
    
    // this is the default contact law
	CrackContactLaw=(ContactDetails *)p;
	CrackContactLaw[0].law=ContactLaw;
	CrackContactLaw[0].friction=friction;
	CrackContactLaw[0].Dn=Dn;
	CrackContactLaw[0].Dnc=Dnc;
	CrackContactLaw[0].Dt=Dt;
}