Misbehavior from processing CMV as point source

I am running nested high-resolution (9 to 1 km) CMV for Pacific Canada (British Columbia) using CRACMM2. I am creating the ptinv and pthour from original MEIT dataset for 2018. My overall approach is to set ship_id as the facility_name and rounding lon/lat to a 3 precision (~1km) and, per-ship, enumerate unique (lat_r, lon_r) positions to produce rel_point_id values starting at 100. I kept unit_id as engine type (ME / AE / BO). I used the 228000 series as my SCC code to be compatible with the EPA platform and assigned them according to the ship’s type and engine type. For instance, I have attached some lines from pthour file here.
pthour.csv (1.2 MB)

To check the output, I didn’t elevate the emissions. However, I am getting a strange behavior from SMOKE in comparison with EPA CMV output.
1. For some pollutants (CO and VOC_INV, PMC), the behavior is correct, and I can see the ship is moving through grids.
2. For some pollutants (particles (such as PCA, PMG, …), NH3, and TOM_INV), all grids within the ship’s path have emissions at all times (no temporal profile), along with the moving grid for the exact location of the ship.
3. NO2, NO, and other VOCs have no emissions, although the profile and reference are provided in the GSREF and GSPRO.
[grdmat.cmv_canada_point.18us.SQ_D01.log.txt

So, If my approach is incorrect, why do I get the correct behavior for CO, VOC_INV, and PMC?

I have attached the logs files.
grdmat.cmv_canada_point.18us.SQ_D01.log.txt (13.3 KB)
smkinven.cmv_canada_point.18us.log.txt (142.6 KB)
smkmerge.cmv_canada_point.18us.20180805.SQ_D01.log.txt (166.0 KB)
spcmat.cmv_canada_point.18us.CRACMM2.log.txt (26.3 KB)
temporal.cmv_canada_point.18us.20180101.log.txt (147.5 KB)

I would appreciate if anyone can provide guidance.

Thanks,
Forood

CO, VOC_INV, and PMC are all mapped (or calculated) at the inventory level while most of the other species are speciated in spcmat. Would you please share your inventory table (INVTABLE), speciation cross-reference (GSREF), and speciation profiles (GSPRO) so that we can verify that these are correctly mapping and speciating the inventory emissions?

Additionally, I notice that you are using SMOKE v4.8.1, which is about 5 years old at this point. Could you please try running with SMOKE v5 or later so that the latest features and bug fixes related to hourly processing are incorporated?

I am using CRACMM2’s invtable, gspro and gsref from 2022 platform.

      setenv INVTABLE "${GE_DAT}/speciation/CRACMM2/invtable_2022platform_nointegrate_11jul2024_nf_v3.txt"
      setenv GSPRO "${GE_DAT}/speciation/CRACMM2/gspro_cmv_cmaq_cracmmv2_P229_2022hc_CRACMM2_nf.txt"
      setenv GSREF "${GE_DAT}/speciation/CRACMM2/gsref_cmv_cmaq_cracmmv2_P229_2022hc_CRACMM2_nf.txt"

I tried SMOKE 5.2.1. I still got the same output.

Here is how I map the vessel’s type to SCC

        cond = [
            fu.eq("diesel") & (act=="underway") & (ecls=="class3") & u.eq("me"),
            fu.eq("diesel") & (act=="underway") & (ecls=="class3") & u.eq("ae"),
            fu.eq("diesel") & (act=="underway") & (ecls!="class3"),
            fu.eq("diesel") & (act!="underway") & (ecls=="class3") & u.eq("me"),
            fu.eq("diesel") & (act!="underway") & (ecls=="class3") & u.eq("ae"),
            fu.eq("diesel") & (act!="underway") & (ecls!="class3"),
            fu.eq("residual") & (act=="underway") & (ecls=="class3") & u.eq("me"),
            fu.eq("residual") & (act=="underway") & (ecls=="class3") & u.eq("ae"),
            fu.eq("residual") & (act=="underway"),
            fu.eq("residual") & (act!="underway") & (ecls=="class3") & u.eq("me"),
            fu.eq("residual") & (act!="underway") & (ecls=="class3") & u.eq("ae"),
            fu.eq("residual") & (act!="underway"),
            (cat=="harbor") & fu.isin(["diesel","unknown"]) & st.str.contains("tug"),
            (cat=="harbor") & fu.isin(["diesel","unknown"]) & st.str.contains("ferry"),
            (cat=="harbor") & fu.isin(["diesel","unknown"]) & st.str.contains("push boat"),
            (cat=="harbor") & fu.isin(["diesel","unknown"]) & st.str.contains("dredge"),
            (cat=="harbor") & fu.isin(["diesel","unknown"]),
            fu.eq("diesel") & (cat=="ocean"),
            fu.eq("diesel") & (cat=="harbor"),
            fu.eq("diesel") & (cat=="fishing"),
            fu.eq("diesel") & (cat=="military"),
            fu.eq("residual") & (cat=="ocean"),
            fu.eq("residual") & (cat=="harbor"),
            fu.eq("residual") & (cat=="fishing"),
            fu.eq("residual") & (cat=="military"),
            fu.eq("gasoline") & (cat=="ocean"),
            fu.eq("gasoline") & (cat=="harbor"),
            fu.eq("gasoline") & (cat=="fishing"),
            fu.eq("gasoline") & (cat=="military"),
        ]
        choices = [
            "2280002203","2280002204","2280002200",
            "2280002103","2280002104","2280002100",
            "2280003203","2280003204","2280003200",
            "2280003103","2280003104","2280003100",
            "2280002021","2280002022","2280002023","2280002025","2280002029",
            "2280002010","2280002020","2280002030","2280002040",
            "2280003010","2280003020","2280003030","2280003040",
            "2280004010","2280004020","2280004030","2280004040",
        ]
        default = "2280000000"
        return pd.Series(np.select(cond, choices, default=default), index=fu.index)

@james.beidler I could fix the issue with NO, NO2, and other VOCs and speciation. It was due to elevpoint program. However, the output looks like the attached figure.

The red spot (which is the location of the ship) is moving though the grids for all pollutants. However, small constant emissions are allocated along with the path of annual emission inventory (light blue color).

@james.beidler I have double-checked my emission inventory and tried different approach in producing the ptinv and pthour files. Manually, I mapped the hourly emissions from pthour file and I got the correct values. However, I am still getting the same output. Is it possible that SMOKE uses temporal profiles from amptref and amptpro instead of hourly values for 1 or 2 SCC codes in the TEMPORAL program?

It is possible if the hourly inventory identifiers (facility ID, rel_point, SCC, etc.) do not exactly match. The fall-back in the platform is to use flat temporal profiles, which matches what you are seeing.