@@ -387,8 +387,9 @@ def test_generate_bcast_fpp_case_opt_guard_sim():
387387 assert "num_fluids" in guard_body
388388 assert "mapped_weno" in guard_body
389389
390- # muscl_eps must NOT appear anywhere (it is excluded — derived post-broadcast)
391- assert "muscl_eps" not in out
390+ # muscl_eps IS inside the case-opt guard (it is sim-only, non-CASE_OPT_PARAM,
391+ # so it appears in the real-scalars section, which is outside the case-opt block)
392+ assert "call MPI_BCAST(muscl_eps, 1, mpi_p, 0, MPI_COMM_WORLD, ierr)" in out
392393
393394
394395def test_generate_bcast_fpp_case_opt_not_in_pre_post ():
@@ -504,8 +505,6 @@ def test_generate_bcast_fpp_excludes_manual_residue():
504505 assert "m_glb" not in out , f"{ target } : m_glb should be manual"
505506 assert "n_glb" not in out , f"{ target } : n_glb should be manual"
506507 assert "p_glb" not in out , f"{ target } : p_glb should be manual"
507- # muscl_eps is excluded (derived post-broadcast)
508- assert "muscl_eps" not in out , f"{ target } : muscl_eps should be excluded"
509508
510509 sim = generate_bcast_fpp ("sim" )
511510 # shear_stress, bulk_stress, bodyForces are derived (non-namelist)
@@ -530,3 +529,95 @@ def test_generate_bcast_fpp_bad_target():
530529
531530 with pytest .raises (ValueError , match = "Unknown target" ):
532531 generate_bcast_fpp ("bad" )
532+
533+
534+ def test_generate_bcast_fpp_muscl_eps_now_broadcast ():
535+ """muscl_eps is broadcast for sim (latent-bug fix: derivation is rank-0-only).
536+
537+ Previously excluded via _BCAST_EXCLUDE; every multi-rank MUSCL run had
538+ rank-divergent muscl_eps because f_is_default() only fires on rank 0.
539+ """
540+ from mfc .params .generators .fortran_gen import generate_bcast_fpp
541+
542+ sim = generate_bcast_fpp ("sim" )
543+ assert "call MPI_BCAST(muscl_eps, 1, mpi_p, 0, MPI_COMM_WORLD, ierr)" in sim
544+
545+ # muscl_eps is sim-only; must not appear in pre/post
546+ pre = generate_bcast_fpp ("pre" )
547+ post = generate_bcast_fpp ("post" )
548+ assert "muscl_eps" not in pre
549+ assert "muscl_eps" not in post
550+
551+
552+ def test_generate_bcast_fpp_fluid_pp_registry_walk ():
553+ """fluid_pp emitter walks registry; no dead members (mul0/ss/pv/gamma_v/M_v/mu_v/k_v/cp_v/D_v removed upstream).
554+
555+ Re(1) count=2 is sim-only; all other registered REAL members appear in all three
556+ targets.
557+ """
558+ from mfc .params .generators .fortran_gen import generate_bcast_fpp
559+
560+ sim = generate_bcast_fpp ("sim" )
561+ pre = generate_bcast_fpp ("pre" )
562+ post = generate_bcast_fpp ("post" )
563+
564+ # All registered members appear in every target
565+ for mem in ("gamma" , "pi_inf" , "cv" , "qv" , "qvp" , "G" ):
566+ for out , t in [(sim , "sim" ), (pre , "pre" ), (post , "post" )]:
567+ assert f"fluid_pp(i)%{ mem } " in out , f"{ t } : fluid_pp(i)%{ mem } missing"
568+
569+ # Re(1) count=2 is sim-only
570+ assert "fluid_pp(i)%Re(1)" in sim
571+ assert "fluid_pp(i)%Re(1)" not in pre
572+ assert "fluid_pp(i)%Re(1)" not in post
573+
574+ # Dead members must not appear
575+ for dead in ("mul0" , "ss" , "pv" , "gamma_v" , "M_v" , "mu_v" , "k_v" , "cp_v" , "D_v" ):
576+ for out , t in [(sim , "sim" ), (pre , "pre" ), (post , "post" )]:
577+ assert f"fluid_pp(i)%{ dead } " not in out , f"{ t } : dead member fluid_pp(i)%{ dead } present"
578+
579+
580+ def test_generate_bcast_fpp_fluid_pp_member_datatypes ():
581+ # The HB merge added a LOGICAL fluid_pp member; datatypes must come from the
582+ # registry, not be assumed REAL.
583+ from mfc .params .generators .fortran_gen import generate_bcast_fpp
584+
585+ sim = generate_bcast_fpp ("sim" )
586+ assert "call MPI_BCAST(fluid_pp(i)%non_newtonian, 1, MPI_LOGICAL," in sim
587+ assert "call MPI_BCAST(fluid_pp(i)%tau0, 1, mpi_p," in sim
588+ assert "non_newtonian, 1, mpi_p" not in sim
589+
590+
591+ def test_generate_bcast_fpp_lag_params_registry_walk ():
592+ """lag_params emitter walks registry; no dead members (T0/Thost/c0/rho0/x0 removed upstream)."""
593+ from mfc .params .generators .fortran_gen import generate_bcast_fpp
594+
595+ sim = generate_bcast_fpp ("sim" )
596+
597+ # All registered members must appear
598+ for mem in ("solver_approach" , "cluster_type" , "smooth_type" , "nBubs_glb" ):
599+ assert f"lag_params%{ mem } " in sim , f"lag_params%{ mem } missing from sim"
600+ for mem in ("heatTransfer_model" , "massTransfer_model" , "pressure_corrector" , "write_bubbles" , "write_bubbles_stats" ):
601+ assert f"lag_params%{ mem } " in sim , f"lag_params%{ mem } missing from sim"
602+ for mem in ("epsilonb" , "charwidth" , "valmaxvoid" ):
603+ assert f"lag_params%{ mem } " in sim , f"lag_params%{ mem } missing from sim"
604+
605+ # Dead members must not appear
606+ for dead in ("T0" , "Thost" , "c0" , "rho0" , "x0" ):
607+ assert f"lag_params%{ dead } " not in sim , f"dead member lag_params%{ dead } present in sim"
608+
609+
610+ def test_mpi_proxy_residue_pins_wall_velocity_and_bc_datatypes ():
611+ """The vb/ve wall-velocity broadcasts and integer BC datatypes live in
612+ hand-written residue (not codegen); pin them so an edit or merge conflict
613+ that drops them fails loudly."""
614+ import pathlib
615+
616+ root = pathlib .Path (__file__ ).resolve ().parents [3 ]
617+ for target in ("pre_process" , "post_process" ):
618+ src = (root / "src" / target / "m_mpi_proxy.fpp" ).read_text ()
619+ assert "bc_${DIM}$%vb${DIR}$" in src , f"{ target } : vb broadcasts missing"
620+ assert "bc_${DIM}$%ve${DIR}$" in src , f"{ target } : ve broadcasts missing"
621+ assert "'bc_x%beg', 'bc_x%end', 'bc_y%beg', 'bc_y%end', 'bc_z%beg', 'bc_z%end']" in src
622+ seg = src .split ("'bc_z%beg', 'bc_z%end']" , 1 )[1 ]
623+ assert "MPI_INTEGER" in seg .split ("#:endfor" )[0 ], f"{ target } : BC codes not MPI_INTEGER"
0 commit comments