@@ -313,12 +313,15 @@ def check_hypoelasticity(self):
313313 """Checks constraints on hypoelasticity parameters"""
314314 hypoelasticity = self .get ('hypoelasticity' , 'F' ) == 'T'
315315 model_eqns = self .get ('model_eqns' )
316+ riemann_solver = self .get ('riemann_solver' )
316317
317318 if not hypoelasticity :
318319 return
319320
320321 self .prohibit (model_eqns != 2 ,
321322 "hypoelasticity requires model_eqns = 2" )
323+ self .prohibit (riemann_solver is not None and riemann_solver != 1 ,
324+ "hypoelasticity requires HLL Riemann solver (riemann_solver = 1)" )
322325
323326 def check_phase_change (self ):
324327 """Checks constraints on phase change parameters"""
@@ -379,7 +382,7 @@ def check_stiffened_eos(self):
379382
380383 if cv is not None :
381384 self .prohibit (cv < 0 ,
382- f"fluid_pp({ i } )%cv must be positive " )
385+ f"fluid_pp({ i } )%cv must be non-negative " )
383386
384387 def check_surface_tension (self ):
385388 """Checks constraints on surface tension"""
@@ -767,12 +770,13 @@ def check_igr_simulation(self): # pylint: disable=too-many-locals
767770 self .prohibit (probe_wrt ,
768771 "IGR does not support probe writes" )
769772
770- # Check BCs
773+ # Check BCs - IGR does not support characteristic BCs
774+ # Characteristic BCs are BC_CHAR_SLIP_WALL (-5) through BC_CHAR_SUP_OUTFLOW (-12)
771775 for dir in ['x' , 'y' , 'z' ]:
772776 for bound in ['beg' , 'end' ]:
773777 bc = self .get (f'bc_{ dir } %{ bound } ' )
774778 if bc is not None :
775- self .prohibit (- 14 <= bc <= - 4 ,
779+ self .prohibit (- 12 <= bc <= - 5 ,
776780 f"Characteristic boundary condition bc_{ dir } %{ bound } is not compatible with IGR" )
777781
778782 def check_acoustic_source (self ): # pylint: disable=too-many-locals,too-many-branches,too-many-statements
@@ -972,15 +976,15 @@ def check_adaptive_time_stepping(self):
972976 adv_n = self .get ('adv_n' , 'F' ) == 'T'
973977
974978 self .prohibit (time_stepper != 3 ,
975- "adapt_dt requires Runge-Kutta 3 (time_stepper = 3)" )
979+ "adap_dt requires Runge-Kutta 3 (time_stepper = 3)" )
976980 self .prohibit (model_eqns == 1 ,
977- "adapt_dt is not supported for model_eqns = 1" )
981+ "adap_dt is not supported for model_eqns = 1" )
978982 self .prohibit (qbmm ,
979- "adapt_dt is not compatible with qbmm" )
983+ "adap_dt is not compatible with qbmm" )
980984 self .prohibit (not polytropic and not bubbles_lagrange ,
981- "adapt_dt requires polytropic = T or bubbles_lagrange = T" )
985+ "adap_dt requires polytropic = T or bubbles_lagrange = T" )
982986 self .prohibit (not adv_n and not bubbles_lagrange ,
983- "adapt_dt requires adv_n = T or bubbles_lagrange = T" )
987+ "adap_dt requires adv_n = T or bubbles_lagrange = T" )
984988
985989 def check_alt_soundspeed (self ):
986990 """Checks alternative sound speed parameters (simulation)"""
@@ -992,13 +996,19 @@ def check_alt_soundspeed(self):
992996 model_eqns = self .get ('model_eqns' )
993997 bubbles_euler = self .get ('bubbles_euler' , 'F' ) == 'T'
994998 avg_state = self .get ('avg_state' )
999+ riemann_solver = self .get ('riemann_solver' )
1000+ num_fluids = self .get ('num_fluids' )
9951001
9961002 self .prohibit (model_eqns != 2 ,
9971003 "5-equation model (model_eqns = 2) is required for alt_soundspeed" )
9981004 self .prohibit (bubbles_euler ,
9991005 "alt_soundspeed is not compatible with bubbles_euler" )
10001006 self .prohibit (avg_state != 2 ,
10011007 "alt_soundspeed requires avg_state = 2" )
1008+ self .prohibit (riemann_solver is not None and riemann_solver != 2 ,
1009+ "alt_soundspeed requires HLLC Riemann solver (riemann_solver = 2)" )
1010+ self .prohibit (num_fluids is not None and num_fluids not in [2 , 3 ],
1011+ "alt_soundspeed requires num_fluids = 2 or 3" )
10021012
10031013 def check_bubbles_lagrange (self ):
10041014 """Checks Lagrangian bubble parameters (simulation)"""
@@ -1009,11 +1019,18 @@ def check_bubbles_lagrange(self):
10091019
10101020 n = self .get ('n' , 0 )
10111021 file_per_process = self .get ('file_per_process' , 'F' ) == 'T'
1022+ model_eqns = self .get ('model_eqns' )
1023+ cluster_type = self .get ('lag_params%cluster_type' )
1024+ smooth_type = self .get ('lag_params%smooth_type' )
10121025
10131026 self .prohibit (n is not None and n == 0 ,
10141027 "bubbles_lagrange accepts 2D and 3D simulations only" )
10151028 self .prohibit (file_per_process ,
10161029 "file_per_process must be false for bubbles_lagrange" )
1030+ self .prohibit (model_eqns == 3 ,
1031+ "The 6-equation flow model does not support bubbles_lagrange" )
1032+ self .prohibit (cluster_type is not None and cluster_type >= 2 and smooth_type != 1 ,
1033+ "cluster_type >= 2 requires smooth_type = 1" )
10171034
10181035 def check_continuum_damage (self ):
10191036 """Checks continuum damage model parameters (simulation)"""
@@ -1023,11 +1040,17 @@ def check_continuum_damage(self):
10231040 return
10241041
10251042 tau_star = self .get ('tau_star' )
1043+ cont_damage_s = self .get ('cont_damage_s' )
1044+ alpha_bar = self .get ('alpha_bar' )
10261045 model_eqns = self .get ('model_eqns' )
10271046 hypoelasticity = self .get ('hypoelasticity' , 'F' ) == 'T'
10281047
10291048 self .prohibit (tau_star is None ,
10301049 "tau_star must be specified for cont_damage" )
1050+ self .prohibit (cont_damage_s is None ,
1051+ "cont_damage_s must be specified for cont_damage" )
1052+ self .prohibit (alpha_bar is None ,
1053+ "alpha_bar must be specified for cont_damage" )
10311054 self .prohibit (model_eqns != 2 ,
10321055 "cont_damage requires model_eqns = 2" )
10331056 self .prohibit (hypoelasticity ,
@@ -1036,24 +1059,35 @@ def check_continuum_damage(self):
10361059 def check_grcbc (self ):
10371060 """Checks Generalized Relaxation Characteristics BC (simulation)"""
10381061 for dir in ['x' , 'y' , 'z' ]:
1039- for loc in ['beg' , 'end' ]:
1040- grcbc_vel = self .get (f'grcbc_vel_{ dir } %{ loc } ' )
1041- bc_val = self .get (f'bc_{ dir } %{ loc } ' )
1042-
1043- if grcbc_vel is not None :
1044- self .prohibit (bc_val != - 14 ,
1045- f"grcbc_vel_{ dir } %{ loc } requires bc_{ dir } %{ loc } = -14 (characteristic BC)" )
1062+ grcbc_in_beg = self .get (f'bc_{ dir } %grcbc_in' )
1063+ grcbc_out_beg = self .get (f'bc_{ dir } %grcbc_out' )
1064+ grcbc_vel_out_beg = self .get (f'bc_{ dir } %grcbc_vel_out' )
1065+ bc_beg = self .get (f'bc_{ dir } %beg' )
1066+ bc_end = self .get (f'bc_{ dir } %end' )
1067+
1068+ if grcbc_in_beg :
1069+ self .prohibit (bc_beg != - 7 and bc_end != - 7 ,
1070+ f"Subsonic Inflow (grcbc_in) requires bc_{ dir } = -7" )
1071+ if grcbc_out_beg :
1072+ self .prohibit (bc_beg != - 8 and bc_end != - 8 ,
1073+ f"Subsonic Outflow (grcbc_out) requires bc_{ dir } = -8" )
1074+ if grcbc_vel_out_beg :
1075+ self .prohibit (bc_beg != - 8 and bc_end != - 8 ,
1076+ f"Subsonic Outflow (grcbc_vel_out) requires bc_{ dir } = -8" )
10461077
10471078 def check_probe_integral_output (self ):
10481079 """Checks probe and integral output requirements (simulation)"""
10491080 probe_wrt = self .get ('probe_wrt' , 'F' ) == 'T'
10501081 integral_wrt = self .get ('integral_wrt' , 'F' ) == 'T'
10511082 fd_order = self .get ('fd_order' )
1083+ bubbles_euler = self .get ('bubbles_euler' , 'F' ) == 'T'
10521084
10531085 self .prohibit (probe_wrt and fd_order is None ,
10541086 "fd_order must be specified for probe_wrt" )
10551087 self .prohibit (integral_wrt and fd_order is None ,
10561088 "fd_order must be specified for integral_wrt" )
1089+ self .prohibit (integral_wrt and not bubbles_euler ,
1090+ "integral_wrt requires bubbles_euler to be enabled" )
10571091
10581092 def check_hyperelasticity (self ):
10591093 """Checks hyperelasticity constraints"""
@@ -1093,9 +1127,9 @@ def check_moving_bc(self): # pylint: disable=too-many-branches
10931127 else : # z
10941128 non_normal = vb1 != 0 or vb2 != 0
10951129
1096- if bc_val == - 15 and non_normal : # BC_SLIP_WALL
1130+ if bc_val == - 15 and non_normal : # BC_SLIP_WALL with non-normal velocities
10971131 self .prohibit (True ,
1098- f"bc_{ direction } %beg must be -15 if non-normal velocities are set" )
1132+ f"bc_{ direction } %beg must be -16 (no-slip wall) if non-normal velocities are set" )
10991133 elif bc_val not in [- 15 , - 16 ]: # Not SLIP or NO_SLIP
11001134 self .prohibit (True ,
11011135 f"bc_{ direction } %beg must be -15 or -16 if velocities are set" )
@@ -1109,9 +1143,9 @@ def check_moving_bc(self): # pylint: disable=too-many-branches
11091143 else : # z
11101144 non_normal = ve1 != 0 or ve2 != 0
11111145
1112- if bc_val == - 15 and non_normal : # BC_SLIP_WALL
1146+ if bc_val == - 15 and non_normal : # BC_SLIP_WALL with non-normal velocities
11131147 self .prohibit (True ,
1114- f"bc_{ direction } %end must be -15 if non-normal velocities are set" )
1148+ f"bc_{ direction } %end must be -16 (no-slip wall) if non-normal velocities are set" )
11151149 elif bc_val not in [- 15 , - 16 ]:
11161150 self .prohibit (True ,
11171151 f"bc_{ direction } %end must be -15 or -16 if velocities are set" )
@@ -1386,8 +1420,6 @@ def check_schlieren(self):
13861420 if schlieren_alpha is not None :
13871421 self .prohibit (schlieren_alpha <= 0 ,
13881422 f"schlieren_alpha({ i } ) must be greater than zero" )
1389- self .prohibit (i > num_fluids ,
1390- f"Index of schlieren_alpha({ i } ) exceeds the total number of fluids" )
13911423 self .prohibit (not schlieren_wrt ,
13921424 f"schlieren_alpha({ i } ) should be set only with schlieren_wrt enabled" )
13931425
@@ -1457,8 +1489,6 @@ def check_partial_density(self):
14571489 if alpha_rho_wrt :
14581490 self .prohibit (model_eqns == 1 ,
14591491 f"alpha_rho_wrt({ i } ) is not supported for model_eqns = 1" )
1460- self .prohibit (i > num_fluids ,
1461- f"Index of alpha_rho_wrt({ i } ) exceeds the total number of fluids" )
14621492
14631493 def check_momentum_post (self ):
14641494 """Checks momentum output constraints (post-process)"""
@@ -1511,8 +1541,6 @@ def check_volume_fraction(self):
15111541 if alpha_wrt :
15121542 self .prohibit (model_eqns == 1 ,
15131543 f"alpha_wrt({ i } ) is not supported for model_eqns = 1" )
1514- self .prohibit (i > num_fluids ,
1515- f"Index of alpha_wrt({ i } ) exceeds the total number of fluids" )
15161544
15171545 def check_fft (self ):
15181546 """Checks FFT output constraints (post-process)"""
@@ -1686,6 +1714,7 @@ def validate(self, stage: str = 'simulation'):
16861714
16871715 Args:
16881716 stage: One of 'simulation', 'pre_process', or 'post_process'
1717+ Other stages (like 'syscheck') have no case constraints and are skipped
16891718
16901719 Raises:
16911720 CaseConstraintError: If any constraint violations are found
@@ -1699,7 +1728,9 @@ def validate(self, stage: str = 'simulation'):
16991728 elif stage == 'post_process' :
17001729 self .validate_post_process ()
17011730 else :
1702- raise ValueError (f"Unknown stage: { stage } " )
1731+ # No stage-specific constraints for auxiliary targets like 'syscheck'.
1732+ # Silently skip validation rather than treating this as an error.
1733+ return
17031734
17041735 if self .errors :
17051736 error_msg = "Case parameter constraint violations:\n " + "\n " .join (f" • { err } " for err in self .errors )
0 commit comments