Skip to content

SO2 to SO4 conversion factor read but set to 0 #111

Description

@lrobion

The input.yaml provides a field SO2 to SO4 conv [%] (double): 2 to convert some of the SO2 emitted by the engine to SO4 to set initial conditions for the chemistry in the plume of the EPM.

This field is read and held in input_.EI_SO2TOSO4(), however it is set to 0 when passing it to the Emission object (what the EPM uses to get EI data):

EI_ = Emission(aircraft_.engine(), jetA_, input_.EI_SO2TOSO4());

This is because for some reason we write a custom assignment constructor for the Emission which forgets to set the SO2toSO4 field, leaving it to the default 0:

Emission& Emission::operator=( const Emission &em )
{
if ( &em == this )
return *this;
CO2 = em.CO2 ;
H2O = em.H2O ;
NOx = em.NOx ;
NO = em.NO ;
NO2 = em.NO2 ;
HNO2= em.HNO2;
SO2 = em.SO2 ;
CO = em.CO ;
HC = em.HC ;
CH4 = em.CH4 ;
C2H6= em.C2H6;
PRPE= em.PRPE;
ALK4= em.ALK4;
CH2O= em.CH2O;
ALD2= em.ALD2;
GLYX= em.GLYX;
MGLY= em.MGLY;
Soot= em.Soot;
SootRad= em.SootRad;
return *this;
} /* End of Emission::operator= */

This is confirmed by adding some print statements here `Core/LAGRIDPlumeModel.cpp:61:

    EI_ = Emission(aircraft_.engine(), jetA_, input_.EI_SO2TOSO4());
    std::cout << "input_.EI_SO2TOSO4()     = " << input_.EI_SO2TOSO4() << std::endl; // prints input_.EI_SO2TOSO4()     = 0.02
    std::cout << "EI_.getSO2toSO4()     = " << EI_.getSO2toSO4() << std::endl; // prints EI_.getSO2toSO4()     = 0

And the effect on the EPM is that the initial SO4 concentration ignores the contribution of the engine EI for SO2. This is confirmed by adding other prints here EPM/Models/Original/Integrate.cpp:182:

        /* Variable SO2 */
        std::cout << "VAR_[ind_SO4] = " << VAR_[ind_SO4] << std::endl; // prints 907100
        VAR_[ind_SO4] += EI_.getSO2toSO4() * EI_.getSO2() / ( MW_H2SO4  * 1.0E+03 ) * aircraft_.FuelFlow() / double(aircraft_.EngNumber()) / aircraft_.VFlight() * Na / Ab0 * 1.00E-06;
        std::cout << "VAR_[ind_SO4] = " << VAR_[ind_SO4] << std::endl; // also prints 907100
        VAR_[ind_SO4] = VAR_[ind_SO4] / n_air_eng;
        std::cout << "VAR_[ind_SO4] converted = " << VAR_[ind_SO4] << std::endl; // prints VAR_[ind_SO4] converted = 2.61654e-13

So the engine EI SO2 contribution is 0 due to the 0 conversion factor, and the initial SO4 concentration for plume chemistry is 2.61654e-13 ~ 1e-13 the ambient number specified by defaults/Ambient.txt (Not sure about the units here). The slight difference is due to the KPP spin up to have the atmosphere in equilibrium.

Effectively I think APCEMM was ignoring the effect of changes in FSC?

Looking at the history of the SO2 to SO4 issues, initially there was a hard coded constant in a header which ignored user input. Then I fixed the user input by passing properly but introduced this bug when I forgot to add it to the assignment constructor. So ignoring FSC contribution would be an issue from the merge of #63 (June 3rd 2025) to now.

APCEMM has a lot of custom copy/assignment constructors and I don't why that was done, but we should probably remove as many as possible as this would prevent bugs like this. The auto-generated ones would just copy/assign everything.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions