/*
	Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved.
*/



/*---------------------- Pro/Toolkit Includes ------------------------*/

#include <ProToolkit.h>
#include <ProMdl.h>
#include <ProMaterial.h>
#include <ProSolid.h>
#include <ProModelitem.h>

/*--------------------------------------------------------------------*\
Application global/external data
\*--------------------------------------------------------------------*/

/*=========================================================================*\
  The structure contains the material properties required for non-linear 
  material definition. Other properties can be added from ProMaterial.h as
  required. 
\*=========================================================================*/

typedef struct matl_proprty_data {

  wchar_t* model;              /*PRO_MATPROP_MODEL,               String*/
  wchar_t* sub_type;           /*PRO_MATPROP_SUB_TYPE             String*/
  ProBool model_def_by_tests;  /*PRO_MATPROP_MODEL_DEF_BY_TESTS,  Boolean*/
  double model_coeff_mu;       /*PRO_MATPROP_MODEL_COEF_MU,       Double*/
  double model_coeff_lm;       /*PRO_MATPROP_MODEL_COEF_LM,       Double*/
  double model_coeff_c01;      /*PRO_MATPROP_MODEL_COEF_C01,      Double*/
  double model_coeff_c02;      /*PRO_MATPROP_MODEL_COEF_C02,      Double*/
  double model_coeff_c10;      /*PRO_MATPROP_MODEL_COEF_C10,      Double*/
  double model_coeff_c11;      /*PRO_MATPROP_MODEL_COEF_C11,      Double*/
  double model_coeff_c20;      /*PRO_MATPROP_MODEL_COEF_C20,      Double*/
  double model_coeff_c30;      /*PRO_MATPROP_MODEL_COEF_C30,      Double*/
  double model_coeff_d;        /*PRO_MATPROP_MODEL_COEF_D,        Double*/
  double model_coeff_d1;       /*PRO_MATPROP_MODEL_COEF_D1,       Double*/
  double model_coeff_d2;       /*PRO_MATPROP_MODEL_COEF_D2,       Double*/
  double model_coeff_d3;       /*PRO_MATPROP_MODEL_COEF_D3,       Double*/

  int type;                             /*PRO_MATPROP_TYPE    
					  Integer*/
  wchar_t* material_description;        /*PRO_MATPROP_MATERIAL_DESCRIPTION
					  WString*/
  wchar_t* failure_criterion_type;      /*PRO_MATPROP_FAILURE_CRITERION_TYPE  
					  WString*/
  wchar_t* fatigue_type;                /*PRO_MATPROP_FATIGUE_TYPE         
					  wString*/
  double thermal_expansion_coefficient; 
                               /*PRO_MATPROP_THERMAL_EXPANSION_COEFFICIENT
				       Double*/
  double specific_heat;                 /*PRO_MATPROP_SPECIFIC_HEAT              
					  Double*/
  double thermal_conductivity;          /*PRO_MATPROP_THERMAL_CONDUCTIVITY       
					  Double*/
  double mass_density;                  /*PRO_MATPROP_MASS_DENSITY               
					  Double*/
  wchar_t* xhatch_file;                 /*PRO_MATPROP_XHATCH_FILE                 
					  WString*/
  double tensile_yield_stress;          /*PRO_MATPROP_TENSILE_YIELD_STRESS        
					  Double*/

}MatrlPropData;

/*---------------------- Function Prototypes -------------------------*/

ProError UsrMaterialItemIntPropertySet (ProMaterialItem* mat_item,
					   ProMaterialPropertyType type,
					   int i_val);

ProError UsrMaterialItemDoublePropertySet (ProMaterialItem* mat_item,
					   ProMaterialPropertyType type,
					   double d_val);

ProError UsrMaterialItemStringPropertySet (ProMaterialItem* mat_item,
					   ProMaterialPropertyType type,
					   wchar_t* s_val);

ProError UsrMaterialItemBoolPropertySet (ProMaterialItem* mat_item,
					 ProMaterialPropertyType type,
					 short l_val);

ProError UsrNonlinMaterialCreate (ProMdl Mdl, MatrlPropData data, 
				  ProName name);


/*====================================================================*\
FUNCTION : UsrNonlinMaterialCreateWrapper
PURPOSE  : To set the new material properties.
\*====================================================================*/
int UsrNonlinMaterialCreateWrapper()
{
  ProMdl mdl;
  MatrlPropData data;
  ProMaterialItem mat_item;
  ProName name;
  int status;

/*--------------------------------------------------------------------*\ 
  Set the new material name 
\*--------------------------------------------------------------------*/ 
  ProStringToWstring (name, "matl_poly2");

  status = ProMdlCurrentGet (&mdl);
  if(status != PRO_TK_NO_ERROR)
    return 0;
  
/*--------------------------------------------------------------------*\ 
  Set the new material properties  
\*--------------------------------------------------------------------*/       
  data.type = PRO_MATERIAL_TYPE_STRUCTURAL_ISOTROPIC | 
    PRO_MATERIAL_TYPE_THERMAL_ISOTROPIC;
  data.material_description = L"taken from spec";

  data.failure_criterion_type = PRO_MATERIAL_FAILURE_DISTORTION_ENERGY;
  data.fatigue_type = PRO_MATERIAL_FATIGUE_TYPE_NONE;
  data.sub_type = PRO_MATERIAL_SUB_TYPE_HYPERELASTIC;

  data.thermal_expansion_coefficient = 4.444000e-05;
  data.specific_heat = 1.444000e+06;
  data.thermal_conductivity = 1.182589e+01;
  data.mass_density = 4.335775e-02;
  data.xhatch_file = L"";

  data.model_def_by_tests = PRO_B_FALSE;

  data.model = PRO_MATERIAL_MODEL_POLYNOMIAL;              

  data.model_coeff_c10 = 8.809880e-01;
  data.model_coeff_c20 = 1.116500e-02;
  data.model_coeff_c01 = 3.780000e-04;
  data.model_coeff_c02 = 1.000000e+00;
  data.model_coeff_c11 = -1.620000e-04;

  data.model_coeff_d1 = 0.00;
  data.model_coeff_d2 = 0.00;

  data.tensile_yield_stress = 2.519884e+06;

/*--------------------------------------------------------------------*\ 
  Call the material create function 
\*--------------------------------------------------------------------*/     
  UsrNonlinMaterialCreate(mdl, data, name);

  return 0;
}

/*====================================================================*\
FUNCTION : UsrNonlinMaterialCreate()
PURPOSE  : To create the new non linear material.
\*====================================================================*/
ProError UsrNonlinMaterialCreate(ProMdl Mdl, MatrlPropData data, 
				 ProName name)
{

  ProMaterialItem mat_item;
  ProMaterial material;

  ProMaterialCreate (Mdl, name,
		     NULL, &material);
 
  ProModelitemByNameInit (Mdl, PRO_RP_MATERIAL, name,
                                   &mat_item);
	
/*--------------------------------------------------------------------*\ 
  Set material properties
\*--------------------------------------------------------------------*/     

  UsrMaterialItemIntPropertySet (&mat_item,
				    PRO_MATPROP_TYPE,
				    data.type);
						
  UsrMaterialItemStringPropertySet (&mat_item,
				    PRO_MATPROP_MATERIAL_DESCRIPTION, 
				    data.material_description);

  UsrMaterialItemStringPropertySet (&mat_item,
				    PRO_MATPROP_FAILURE_CRITERION_TYPE, 
				    data.failure_criterion_type);

  UsrMaterialItemStringPropertySet (&mat_item,
				    PRO_MATPROP_FATIGUE_TYPE, 
				    data.fatigue_type);

  UsrMaterialItemStringPropertySet (&mat_item,
				    PRO_MATPROP_SUB_TYPE, 
				    data.sub_type);

  UsrMaterialItemDoublePropertySet (&mat_item,
				    PRO_MATPROP_THERMAL_EXPANSION_COEFFICIENT, 
				    data.thermal_expansion_coefficient);

  UsrMaterialItemDoublePropertySet (&mat_item,
				    PRO_MATPROP_SPECIFIC_HEAT, 
				    data.specific_heat);

  UsrMaterialItemDoublePropertySet (&mat_item,
				    PRO_MATPROP_THERMAL_CONDUCTIVITY, 
				    data.thermal_conductivity);

  UsrMaterialItemDoublePropertySet (&mat_item,
				    PRO_MATPROP_MASS_DENSITY, 
				    data.mass_density);

  UsrMaterialItemStringPropertySet (&mat_item,
				    PRO_MATPROP_XHATCH_FILE, 
				    data.xhatch_file);
 
  UsrMaterialItemBoolPropertySet (&mat_item,
				  PRO_MATPROP_MODEL_DEF_BY_TESTS, 
				  data.model_def_by_tests);

  UsrMaterialItemStringPropertySet (&mat_item,
				    PRO_MATPROP_MODEL, 
				    data.model);

  UsrMaterialItemDoublePropertySet (&mat_item,
				    PRO_MATPROP_MODEL_COEF_C10, 
				    data.model_coeff_c10);

  UsrMaterialItemDoublePropertySet (&mat_item,
				    PRO_MATPROP_MODEL_COEF_C01, 
				    data.model_coeff_c01);
						
  UsrMaterialItemDoublePropertySet (&mat_item,
				    PRO_MATPROP_MODEL_COEF_C20, 
				    data.model_coeff_c20);
  
  UsrMaterialItemDoublePropertySet (&mat_item,
				    PRO_MATPROP_MODEL_COEF_C02, 
				    data.model_coeff_c02);

  UsrMaterialItemDoublePropertySet (&mat_item,
				    PRO_MATPROP_MODEL_COEF_C11, 
				    data.model_coeff_c11);

  UsrMaterialItemDoublePropertySet (&mat_item,
				    PRO_MATPROP_MODEL_COEF_D1, 
				    data.model_coeff_d1);

  UsrMaterialItemDoublePropertySet (&mat_item,
				    PRO_MATPROP_MODEL_COEF_D2, 
				    data.model_coeff_d2);

  UsrMaterialItemDoublePropertySet (&mat_item,
				    PRO_MATPROP_TENSILE_YIELD_STRESS, 
				    data.tensile_yield_stress);

  return PRO_TK_NO_ERROR;
}


/*====================================================================*\
FUNCTION : UsrMaterialItemBoolPropertySet()
PURPOSE  : To set material property of type ProBool.
\*====================================================================*/

ProError UsrMaterialItemBoolPropertySet (ProMaterialItem* mat_item,
					   ProMaterialPropertyType type,
					   short l_val)
{
  ProParamvalue value;
  
  value.type = PRO_PARAM_BOOLEAN;
  value.value.l_val = l_val;

  ProMaterialPropertySet (mat_item, type, &value, NULL);

  return PRO_TK_NO_ERROR;

}


/*====================================================================*\
FUNCTION : UsrMaterialItemIntPropertySet()
PURPOSE  : To set material property of type integer.
\*====================================================================*/

ProError UsrMaterialItemIntPropertySet (ProMaterialItem* mat_item,
					   ProMaterialPropertyType type,
					   int i_val)
{
  ProParamvalue value;
  
  value.type = PRO_PARAM_INTEGER;
  value.value.i_val = i_val;

  ProMaterialPropertySet  (mat_item, type, &value, NULL);

  return PRO_TK_NO_ERROR;

}


/*====================================================================*\
FUNCTION : UsrMaterialItemDoublePropertySet()
PURPOSE  : To set material property of type double.
\*====================================================================*/

ProError UsrMaterialItemDoublePropertySet (ProMaterialItem* mat_item,
					   ProMaterialPropertyType type,
					   double d_val)
{
  ProParamvalue value;
  ProUnititem units;
  ProParamvalue old_val;
  int err;
  
  value.type = PRO_PARAM_DOUBLE;
  value.value.d_val = d_val;

  err = ProMaterialPropertyGet (mat_item, type, &old_val, &units);

  if (err == PRO_TK_E_NOT_FOUND)
    ProMaterialPropertySet  (mat_item, type, &value, NULL);
  else
    ProMaterialPropertySet  (mat_item, type, &value, &units);

  return PRO_TK_NO_ERROR;
}

/*====================================================================*\
FUNCTION : UsrMaterialItemStringPropertySet()
PURPOSE  : To set material property of type string
\*====================================================================*/

ProError UsrMaterialItemStringPropertySet (ProMaterialItem* mat_item,
					   ProMaterialPropertyType type,
					   wchar_t* s_val)
{
  ProParamvalue value;
  
  value.type = PRO_PARAM_STRING;
  ProWstringCopy (s_val, value.value.s_val, PRO_VALUE_UNUSED);

  ProMaterialPropertySet  (mat_item, type, &value, NULL);

  return PRO_TK_NO_ERROR;

}