! ============================================================
! M12 - Union atornillada idealizada
! Dos placas SOLID185 unidas por nodos piloto + CERIG + conector 1D.
! Casos: MPC184 (viga rigida) y BEAM188 (rigidez elastica).
! Unidades coherentes: m, kg, s, N, Pa.
! ============================================================

/CLEAR,START
/FILNAME,m12_bolt,1
/TITLE,M12 - Union atornillada idealizada
/UNITS,SI

plate_x=0.08
plate_z=0.04
plate_t=0.012
interface_gap=0.0001
mesh_h=0.004
bolt_x=0.04
bolt_z=0.02
head_absorb_r=0.010
thread_absorb_r=0.008
bolt_d=0.012
young=210E9
nu=0.30
fx_total=4000
fy_total=-3000
select_tol=mesh_h*1E-4
equilibrium_tol=0.005
force_match_tol=0.08
min_head_dep=4
min_thread_dep=4

! ============================================================
! CASO 1 - MPC184 RIGID BEAM (KEYOPT 1=1, 2=1)
! ============================================================
/PREP7
ET,1,SOLID185
KEYOPT,1,2,0
ET,2,MPC184
KEYOPT,2,1,1
KEYOPT,2,2,1
MP,EX,1,young
MP,PRXY,1,nu
MP,EX,2,young
MP,PRXY,2,nu
TYPE,1
MAT,1
BLOCK,0,plate_x,0,plate_t,0,plate_z
BLOCK,0,plate_x,plate_t+interface_gap,2*plate_t+interface_gap,0,plate_z

div_x=MAX(1,NINT(plate_x/mesh_h))
div_y=MAX(1,NINT(plate_t/mesh_h))
div_z=MAX(1,NINT(plate_z/mesh_h))
MSHAPE,0,3D
MSHKEY,1
LSEL,S,LENGTH,,plate_x
LESIZE,ALL,,,div_x,,1
LSEL,S,LENGTH,,plate_t
LESIZE,ALL,,,div_y,,1
LSEL,S,LENGTH,,plate_z
LESIZE,ALL,,,div_z,,1
ALLSEL,ALL
VMESH,ALL

*GET,n_nodes,NODE,0,COUNT
*GET,n_solid,ELEM,0,COUNT

SELTOL,select_tol
NSEL,S,LOC,Y,0
CM,bottom_nodes,NODE
*GET,n_bottom,NODE,0,COUNT
NSEL,S,LOC,Y,2*plate_t+interface_gap
CM,top_load_nodes,NODE
*GET,n_top_load,NODE,0,COUNT
ALLSEL,ALL
SELTOL,

SELTOL,select_tol
NSEL,S,LOC,Y,2*plate_t+interface_gap
NSEL,R,LOC,X,bolt_x-head_absorb_r,bolt_x+head_absorb_r
NSEL,R,LOC,Z,bolt_z-head_absorb_r,bolt_z+head_absorb_r
CM,head_dep,NODE
*GET,n_head_dep,NODE,0,COUNT
CMSEL,S,head_dep
NSEL,R,LOC,X,bolt_x-select_tol,bolt_x+select_tol
NSEL,R,LOC,Z,bolt_z-select_tol,bolt_z+select_tol
*GET,head_pilot,NODE,0,NUM,MIN
CMSEL,S,head_dep
CERIG,head_pilot,ALL,UX,UY,UZ
ALLSEL,ALL

NSEL,S,LOC,Y,plate_t
NSEL,R,LOC,X,bolt_x-thread_absorb_r,bolt_x+thread_absorb_r
NSEL,R,LOC,Z,bolt_z-thread_absorb_r,bolt_z+thread_absorb_r
CM,thread_dep,NODE
*GET,n_thread_dep,NODE,0,COUNT
CMSEL,S,thread_dep
NSEL,R,LOC,X,bolt_x-select_tol,bolt_x+select_tol
NSEL,R,LOC,Z,bolt_z-select_tol,bolt_z+select_tol
*GET,thread_pilot,NODE,0,NUM,MIN
CMSEL,S,thread_dep
CERIG,thread_pilot,ALL,UX,UY,UZ
ALLSEL,ALL
SELTOL,

TYPE,2
REAL,1
MAT,2
E,head_pilot,thread_pilot
*GET,conn_elem,ELEM,0,NUM,MAX
ALLSEL,ALL
FINISH

/SOLU
ANTYPE,STATIC
NLGEOM,OFF
CMSEL,S,bottom_nodes
D,ALL,ALL,0
ALLSEL,ALL
F,head_pilot,FX,fx_total
F,head_pilot,FY,fy_total
ALLSEL,ALL
OUTRES,ALL,LAST
SOLVE
FINISH

/POST1
SET,LAST
*GET,uy_head_mpc,NODE,head_pilot,U,Y
*GET,ux_head_mpc,NODE,head_pilot,U,X

ETABLE,mpc_fx,SMISC,1
ETABLE,mpc_my,SMISC,2
ETABLE,mpc_mz,SMISC,3
ETABLE,mpc_mx,SMISC,4
ETABLE,mpc_fz,SMISC,5
ETABLE,mpc_fy,SMISC,6
*GET,mpc_fx,ELEM,conn_elem,ETAB,mpc_fx
*GET,mpc_fy,ELEM,conn_elem,ETAB,mpc_fy
*GET,mpc_fz,ELEM,conn_elem,ETAB,mpc_fz
*GET,mpc_mx,ELEM,conn_elem,ETAB,mpc_mx
*GET,mpc_my,ELEM,conn_elem,ETAB,mpc_my
*GET,mpc_mz,ELEM,conn_elem,ETAB,mpc_mz

rfx_mpc=0
rfy_mpc=0
rfz_mpc=0
CMSEL,S,bottom_nodes
node_id=0
*DO,j,1,n_bottom
  node_id=NDNEXT(node_id)
  *GET,rfx_node,NODE,node_id,RF,FX
  *GET,rfy_node,NODE,node_id,RF,FY
  *GET,rfz_node,NODE,node_id,RF,FZ
  rfx_mpc=rfx_mpc+rfx_node
  rfy_mpc=rfy_mpc+rfy_node
  rfz_mpc=rfz_mpc+rfz_node
*ENDDO
ALLSEL,ALL
FINISH

ferr_mpc=SQRT((rfx_mpc+fx_total)**2+(rfy_mpc+fy_total)**2)/SQRT(fx_total**2+fy_total**2)

PARSAV,ALL,m12_state,par

! ============================================================
! CASO 2 - BEAM188 ELASTICO
! ============================================================
/CLEAR,NOSTART
/FILNAME,m12_beam,1
/TITLE,M12 - BEAM188 elastico
/UNITS,SI
PARRES,NEW,m12_state,par
select_tol=mesh_h*1E-4

/PREP7
ET,1,SOLID185
KEYOPT,1,2,0
ET,2,BEAM188
MP,EX,1,young
MP,PRXY,1,nu
MP,EX,2,young
MP,PRXY,2,nu
SECTYPE,1,BEAM,CSOLID
SECDATA,bolt_d
TYPE,1
MAT,1
BLOCK,0,plate_x,0,plate_t,0,plate_z
BLOCK,0,plate_x,plate_t+interface_gap,2*plate_t+interface_gap,0,plate_z
div_x=MAX(1,NINT(plate_x/mesh_h))
div_y=MAX(1,NINT(plate_t/mesh_h))
div_z=MAX(1,NINT(plate_z/mesh_h))
MSHAPE,0,3D
MSHKEY,1
LSEL,S,LENGTH,,plate_x
LESIZE,ALL,,,div_x,,1
LSEL,S,LENGTH,,plate_t
LESIZE,ALL,,,div_y,,1
LSEL,S,LENGTH,,plate_z
LESIZE,ALL,,,div_z,,1
ALLSEL,ALL
VMESH,ALL

SELTOL,select_tol
NSEL,S,LOC,Y,0
CM,bottom_nodes,NODE
*GET,n_bottom,NODE,0,COUNT
NSEL,S,LOC,Y,2*plate_t+interface_gap
CM,top_load_nodes,NODE
*GET,n_top_load,NODE,0,COUNT
ALLSEL,ALL
SELTOL,

SELTOL,select_tol
NSEL,S,LOC,Y,2*plate_t+interface_gap
NSEL,R,LOC,X,bolt_x-head_absorb_r,bolt_x+head_absorb_r
NSEL,R,LOC,Z,bolt_z-head_absorb_r,bolt_z+head_absorb_r
CM,head_dep,NODE
*GET,n_head_dep_beam,NODE,0,COUNT
CMSEL,S,head_dep
NSEL,R,LOC,X,bolt_x-select_tol,bolt_x+select_tol
NSEL,R,LOC,Z,bolt_z-select_tol,bolt_z+select_tol
*GET,head_pilot,NODE,0,NUM,MIN
CMSEL,S,head_dep
CERIG,head_pilot,ALL,UX,UY,UZ
ALLSEL,ALL

NSEL,S,LOC,Y,plate_t
NSEL,R,LOC,X,bolt_x-thread_absorb_r,bolt_x+thread_absorb_r
NSEL,R,LOC,Z,bolt_z-thread_absorb_r,bolt_z+thread_absorb_r
CM,thread_dep,NODE
*GET,n_thread_dep_beam,NODE,0,COUNT
CMSEL,S,thread_dep
NSEL,R,LOC,X,bolt_x-select_tol,bolt_x+select_tol
NSEL,R,LOC,Z,bolt_z-select_tol,bolt_z+select_tol
*GET,thread_pilot,NODE,0,NUM,MIN
CMSEL,S,thread_dep
CERIG,thread_pilot,ALL,UX,UY,UZ
ALLSEL,ALL
SELTOL,

TYPE,2
REAL,1
MAT,2
SECNUM,1
E,head_pilot,thread_pilot
*GET,conn_elem_beam,ELEM,0,NUM,MAX
ALLSEL,ALL
FINISH

/SOLU
ANTYPE,STATIC
NLGEOM,OFF
CMSEL,S,bottom_nodes
D,ALL,ALL,0
ALLSEL,ALL
F,head_pilot,FX,fx_total
F,head_pilot,FY,fy_total
ALLSEL,ALL
OUTRES,ALL,LAST
SOLVE
FINISH

/POST1
SET,LAST
*GET,uy_head_beam,NODE,head_pilot,U,Y
*GET,ux_head_beam,NODE,head_pilot,U,X

ETABLE,beam_fx,SMISC,1
ETABLE,beam_my,SMISC,2
ETABLE,beam_mz,SMISC,3
ETABLE,beam_mx,SMISC,4
ETABLE,beam_fz,SMISC,5
ETABLE,beam_fy,SMISC,6
*GET,beam_fx,ELEM,conn_elem_beam,ETAB,beam_fx
*GET,beam_fy,ELEM,conn_elem_beam,ETAB,beam_fy
*GET,beam_fz,ELEM,conn_elem_beam,ETAB,beam_fz
*GET,beam_mx,ELEM,conn_elem_beam,ETAB,beam_mx
*GET,beam_my,ELEM,conn_elem_beam,ETAB,beam_my
*GET,beam_mz,ELEM,conn_elem_beam,ETAB,beam_mz

rfx_beam=0
rfy_beam=0
rfz_beam=0
CMSEL,S,bottom_nodes
node_id=0
*DO,j,1,n_bottom
  node_id=NDNEXT(node_id)
  *GET,rfx_node,NODE,node_id,RF,FX
  *GET,rfy_node,NODE,node_id,RF,FY
  *GET,rfz_node,NODE,node_id,RF,FZ
  rfx_beam=rfx_beam+rfx_node
  rfy_beam=rfy_beam+rfy_node
  rfz_beam=rfz_beam+rfz_node
*ENDDO
ALLSEL,ALL
FINISH

ferr_beam=SQRT((rfx_beam+fx_total)**2+(rfy_beam+fy_total)**2)/SQRT(fx_total**2+fy_total**2)
fx_diff=ABS(mpc_fx-beam_fx)/MAX(ABS(mpc_fx),ABS(beam_fx),1)
fy_diff=ABS(mpc_fy-beam_fy)/MAX(ABS(mpc_fy),ABS(beam_fy),1)
axial_ref=ABS(fy_total)
shear_ref=ABS(fx_total)
axial_mpc_err=ABS(ABS(mpc_fx)-axial_ref)/axial_ref
shear_mpc_err=ABS(ABS(mpc_fy)-shear_ref)/shear_ref
axial_beam_err=ABS(ABS(beam_fx)-axial_ref)/axial_ref
shear_beam_err=ABS(ABS(beam_fy)-shear_ref)/shear_ref
uy_diff=ABS(uy_head_mpc-uy_head_beam)/MAX(ABS(uy_head_mpc),ABS(uy_head_beam),1E-12)

! ============================================================
! AUDITORIA Y CONTRATO
! ============================================================
passes=1
*IF,n_nodes,LT,200,THEN
  passes=0
*ENDIF
*IF,n_solid,LT,80,THEN
  passes=0
*ENDIF
*IF,n_head_dep,LT,min_head_dep,THEN
  passes=0
*ENDIF
*IF,n_thread_dep,LT,min_thread_dep,THEN
  passes=0
*ENDIF
*IF,n_head_dep_beam,NE,n_head_dep,THEN
  passes=0
*ENDIF
*IF,n_thread_dep_beam,NE,n_thread_dep,THEN
  passes=0
*ENDIF
*IF,ferr_mpc,GE,equilibrium_tol,THEN
  passes=0
*ENDIF
*IF,ferr_beam,GE,equilibrium_tol,THEN
  passes=0
*ENDIF
*IF,axial_mpc_err,GT,force_match_tol,THEN
  passes=0
*ENDIF
*IF,shear_mpc_err,GT,force_match_tol,THEN
  passes=0
*ENDIF
*IF,axial_beam_err,GT,force_match_tol,THEN
  passes=0
*ENDIF
*IF,shear_beam_err,GT,force_match_tol,THEN
  passes=0
*ENDIF
*IF,fx_diff,GT,force_match_tol,THEN
  passes=0
*ENDIF
*IF,fy_diff,GT,force_match_tol,THEN
  passes=0
*ENDIF

*CFOPEN,m12_connector_audit,csv
*VWRITE
('case,connector,n_nodes,n_solid,n_head_dep,n_thread_dep,N_local_N,V1_local_N,V2_local_N,mx_Nm,my_Nm,mz_Nm,uy_head_m,ux_head_m,force_error,passes')
*VWRITE,'mpc',n_nodes,n_solid,n_head_dep,n_thread_dep,mpc_fx,mpc_fy,mpc_fz,mpc_mx,mpc_my,mpc_mz,uy_head_mpc,ux_head_mpc,ferr_mpc,passes
(A4,',',F10.0,',',F10.0,',',F10.0,',',F10.0,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',F2.0)
*VWRITE,'beam',n_nodes,n_solid,n_head_dep_beam,n_thread_dep_beam,beam_fx,beam_fy,beam_fz,beam_mx,beam_my,beam_mz,uy_head_beam,ux_head_beam,ferr_beam,passes
(A4,',',F10.0,',',F10.0,',',F10.0,',',F10.0,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',F2.0)
*CFCLOS

*CFOPEN,m12_summary,csv
*VWRITE
('n_nodes,n_solid,n_head_dep,n_thread_dep,axial_mpc_err,shear_mpc_err,axial_beam_err,shear_beam_err,uy_diff_ratio,study_passes')
*VWRITE,n_nodes,n_solid,n_head_dep,n_thread_dep,axial_mpc_err,shear_mpc_err,axial_beam_err,shear_beam_err,uy_diff,passes
(F8.0,',',F8.0,',',F8.0,',',F8.0,',',F10.6,',',F10.6,',',F10.6,',',F10.6,',',F10.6,',',I1)
*CFCLOS

*CFOPEN,m12_bolt_forces,csv
*VWRITE
('connector,N_local_N,V1_local_N,V2_local_N,mx_Nm,my_Nm,mz_Nm,note')
*VWRITE,'mpc',mpc_fx,mpc_fy,mpc_fz,mpc_mx,mpc_my,mpc_mz
(A4,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',','export_for_external_code_check')
*VWRITE,'beam',beam_fx,beam_fy,beam_fz,beam_mx,beam_my,beam_mz
(A4,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',',E16.8,',','export_for_external_code_check')
*CFCLOS

*IF,passes,EQ,1,THEN
  /COM,M12 BOLT CONNECTOR STUDY PASSED
*ELSE
  /COM,M12 BOLT CONNECTOR STUDY FAILED - inspect m12_connector_audit.csv and .out
  /STATUS,PARM
*ENDIF

FINISH
