# EXPORT CONTROLLED — ITAR USML Category XX  (Ocean Guard M05A)
# Code_Aster STAT_NON_LINE hyperelastic O-ring/groove squeeze — AS568A-333 EPDM 90A.
# Auto-generated by oring_hyperelastic_comm.py. Do not hand-edit.
DEBUT(LANG='EN')

MESH = LIRE_MAILLAGE(FORMAT='MED', UNITE=20)

# D_PLAN (plane strain), not AXIS — see module docstring 2026-07-09 note
# (ELASHYPER_97: this Aster build forbids ELAS_HYPER+AXIS outright).
MODEL = AFFE_MODELE(
    MAILLAGE=MESH,
    AFFE=_F(TOUT='OUI', PHENOMENE='MECANIQUE', MODELISATION='D_PLAN'),
)

# EPDM 90A hyperelastic Mooney-Rivlin (dual-oring-sealing skill FEM baseline).
MAT = DEFI_MATERIAU(
    ELAS_HYPER=_F(C10=5.500000e+05, C01=1.400000e+05, C20=0.0, K=2.000000e+09),
)

FIELDMAT = AFFE_MATERIAU(MAILLAGE=MESH, AFFE=_F(TOUT='OUI', MATER=MAT))

# Groove floor fixed. Gland face ramps to the full squeeze displacement
# (0.9800 mm = 21.9% squeeze on CS=4.47mm).
# GROOVE_FLOOR alone (full DX=DY=0 over a non-degenerate 2D edge) already
# removes all 3 planar rigid-body modes of this D_PLAN model — see
# generate_oring_comm_file() docstring, 2026-07-10 CONTACT-BC fix note.
LOAD_FIXED = AFFE_CHAR_MECA(
    MODELE=MODEL,
    DDL_IMPO=_F(GROUP_MA='GROOVE_FLOOR', DX=0.0, DY=0.0),
)

RAMP = DEFI_FONCTION(
    NOM_PARA='INST',
    VALE=(0.0, 0.0, 1.0, 1.0),
    PROL_DROITE='CONSTANT', PROL_GAUCHE='CONSTANT',
)

LOAD_SQUEEZE = AFFE_CHAR_MECA(
    MODELE=MODEL,
    DDL_IMPO=_F(GROUP_MA='GLAND_FACE', DY=9.800000e-04),
)

LINST = DEFI_LIST_REEL(DEBUT=0.0, INTERVALLE=_F(JUSQU_A=1.0, NOMBRE=40))

DLIST = DEFI_LIST_INST(
    METHODE='AUTO',
    DEFI_LIST=_F(LIST_INST=LINST),
    ECHEC=_F(ACTION='DECOUPE', SUBD_METHODE='MANUEL', SUBD_PAS=4, SUBD_NIVEAU=6),
)

# STAT_NON_LINE — large displacement + hyperelastic (ELAS_HYPER).
# NOTE (2026-07-08 fix, COMPOR1_44): Code_Aster 17.4 rejects
# DEFORMATION='GROT_GDEP' combined with RELATION='ELAS_HYPER'
# ("<EXCEPTION> <COMPOR1_44> Le type de deformation choisi <GROT_GDEP> est
# incompatible avec le comportement <ELAS_HYPER>") — box-confirmed real
# run, first real STAT_NON_LINE attempt on this .comm. Same class of fix
# already applied in gate_codeaster_nonlinear.py's generate_comm_file()
# (that file's own 2026-07-03 COMPOR5_22 note): Aster's own exception text
# recommends GREEN_LAGRANGE as the large-strain-compatible alternative for
# hyperelastic materials on this mesh/element combination.
# NOTE (2026-07-10 fix, MECANONLINE9_4): CONTACT= removed — see module
# docstring "CONTACT-BC FIX" section. GROOVE_FLOOR + GLAND_FACE's own
# independent Dirichlet BCs fully determine this model without it.
RESU = STAT_NON_LINE(
    MODELE=MODEL,
    CHAM_MATER=FIELDMAT,
    EXCIT=(
        _F(CHARGE=LOAD_FIXED),
        _F(CHARGE=LOAD_SQUEEZE, FONC_MULT=RAMP),
    ),
    COMPORTEMENT=_F(RELATION='ELAS_HYPER', DEFORMATION='GREEN_LAGRANGE', TOUT='OUI'),
    INCREMENT=_F(LIST_INST=DLIST),
    NEWTON=_F(MATRICE='TANGENTE', REAC_ITER=1),
    CONVERGENCE=_F(RESI_GLOB_RELA=1.0e-5, ITER_GLOB_MAXI=30),
)

RESU = CALC_CHAMP(reuse=RESU, RESULTAT=RESU, CONTRAINTE=('SIEF_NOEU',), FORCE=('REAC_NODA',))

IMPR_RESU(FORMAT='RESULTAT', RESU=_F(RESULTAT=RESU, NOM_CHAM='DEPL'))

# Reaction-force contact-pressure proxy (2026-07-10 fix — replaces the
# redundant DEFI_CONTACT/LAGR_C extraction; see module docstring
# "CONTACT-PRESSURE EXTRACTION — REVISED"). GLAND_FACE already carries a
# complete, independent DDL_IMPO(DY=squeeze) Dirichlet BC — STAT_NON_LINE
# computes REAC_NODA (the reaction force needed to hold that prescribed
# displacement) natively at every constrained node, no CONTACT block
# required. In a compressed-slab idealization (this D_PLAN cross-section:
# fixed GROOVE_FLOOR / prescribed-displaced GLAND_FACE), the reaction force
# at the prescribed face divided by its contact width IS the interface
# contact pressure. GLAND_FACE's real in-plane width equals the O-ring
# cross-section CS_MM (4.47mm — bbox-confirmed in
# KD-CODEASTER-ORING-CONTACT-SINGULAR-2026-07-09.md: GLAND_FACE spans
# x=[147.765,152.235]mm = 4.47mm = CS_MM exactly). D_PLAN reports REAC_NODA
# as a force-per-unit-out-of-plane-depth (Aster's plane-strain convention
# treats the model as 1m thick); dividing the summed DY reaction by the
# real in-plane width converts N/m -> Pa, i.e. contact pressure.
TAB_REAC = POST_RELEVE_T(
    ACTION=_F(INTITULE='GLAND_REACTION', GROUP_NO='GLAND_FACE', RESULTAT=RESU,
              NOM_CHAM='REAC_NODA', NOM_CMP='DY', OPERATION='SOMME'),
)

# Deterministic Python-level marker (unchanged format from Round-1 — see
# module docstring) so downstream parsing needs no changes.
_gland_width_m = 4.470000e-03
_max_contact_pa = 0.0
try:
    _arr = TAB_REAC.EXTR_TABLE().Array('INTITULE', 'DY')
    _reac_dy_n = abs(float(_arr[0][1])) if len(_arr) else 0.0
    _max_contact_pa = _reac_dy_n / _gland_width_m if _gland_width_m > 0.0 else 0.0
except Exception:
    import re as _re
    _raw = str(TAB_REAC)
    _nums = _re.findall(r"[-+]?\d+\.\d+E[-+]\d+", _raw)
    _vals = [abs(float(n)) for n in _nums]
    _reac_dy_n = max(_vals) if _vals else 0.0
    _max_contact_pa = _reac_dy_n / _gland_width_m if _gland_width_m > 0.0 else 0.0

print("OG_CONTACT_PRESSURE_PA=%.6E" % _max_contact_pa)
print("OG_CONTACT_GATE_MPA=%.4f" % 30.0000)

FIN()
