Peano
Loading...
Searching...
No Matches
AirglowPDE.py
Go to the documentation of this file.
2 return """
3 const {{COMPUTE_PRECISION}} u_n = Q[Shortcuts::u + normal];
4 return std::fabs(u_n);
5 """
6
7
8def get_flux():
9 return """// set flux for all densities to zero
10 for (int unknown = 0; unknown < {{NUMBER_OF_UNKNOWNS}}; ++unknown) {
11 F[unknown] = 0.0;
12 }
13
14 // based on Snively et al. "OH and OI airglow layer modulation by ducted short-period gravity waves: Effects of trapping altitude", 2009
15 // advect only those species, which have lifetimes long enough to be affected by gravity waves
16
17 // advect major species densities
18 const {{COMPUTE_PRECISION}} u_n = Q[Shortcuts::u + normal];
19 F[Shortcuts::O] = u_n * Q[Shortcuts::O];
20 F[Shortcuts::O2] = u_n * Q[Shortcuts::O2];
21 F[Shortcuts::N2] = u_n * Q[Shortcuts::N2];
22
23 // advect long-lived minor species densities
24 F[Shortcuts::O3] = u_n * Q[Shortcuts::O3];
25 F[Shortcuts::H] = u_n * Q[Shortcuts::H];"""
26
27
29 """!
30 Returns source term of production and loss for minor species.
31 """
32 return """using ProductionRates = applications::exahype2::GravityWaves::Airglow::ProductionRates;
33
34 const {{COMPUTE_PRECISION}} O = Q[Shortcuts::O]; // atomic oxygen
35 const {{COMPUTE_PRECISION}} O2 = Q[Shortcuts::O2]; // molecular oxygen
36 const {{COMPUTE_PRECISION}} N2 = Q[Shortcuts::N2]; // nitrogen
37 const {{COMPUTE_PRECISION}} O3 = Q[Shortcuts::O3]; // ozone
38 const {{COMPUTE_PRECISION}} H = Q[Shortcuts::H]; // hydrogen
39 const {{COMPUTE_PRECISION}} M = O + O2 + N2; // total major species density
40 const {{COMPUTE_PRECISION}} T = Q[Shortcuts::T];
41 const int BANDWIDTH = EINSTEIN_BANDWIDTH;
42
43 // set source term for all densities to zero
44 for (int unknown = 0; unknown < NumberOfUnknowns; ++unknown) {
45 S[unknown] = 0.0;
46 }
47
48 /*****************
49 * Major species *
50 *****************/
51 // major species do not have any loss or production
52 // as it is assumed negligible
53 S[Shortcuts::O] = 0.0;
54 S[Shortcuts::O2] = 0.0;
55 S[Shortcuts::N2] = 0.0;
56
57 /*******************************
58 * Production of minor species *
59 *******************************/
60
61 // k6 production of ozone
62 S[Shortcuts::O3] += (ProductionRates::k6(T) * M * O * O2);
63 S[Shortcuts::H] = 0.0;
64
65 // OH model production
66 for (int vibrationalState = 0; vibrationalState < 10; ++vibrationalState) {
67 const int stateIndex = Shortcuts::OH0 + vibrationalState;
68
69 // k7 production of hydrogen
70 S[Shortcuts::H] += ProductionRates::k7(vibrationalState) * O * Q[stateIndex];
71
72 // k5 production of OH(v)
73 S[stateIndex] += ProductionRates::k5(T, vibrationalState) * H * O3;
74
75 if (vibrationalState < 9) {
76 // production via Einstein coefficients by quenching from higher states within bandwidth
77 for (int higherVibrationalState = std::min(vibrationalState + BANDWIDTH, 9); higherVibrationalState > vibrationalState; --higherVibrationalState) {
78 S[stateIndex] += EINSTEIN_COEFFICIENTS(higherVibrationalState, vibrationalState) * Q[Shortcuts::OH0 + higherVibrationalState];
79 }
80
81 // production via k8 by quenching from all higher states
82 for (int higherVibrationalState = 9; higherVibrationalState > vibrationalState; --higherVibrationalState) {
83 S[stateIndex] += ProductionRates::k8(higherVibrationalState, vibrationalState) * O2 * Q[Shortcuts::OH0 + higherVibrationalState];
84 }
85
86 // production via k9 by quenching from next higher vibrational state
87 S[stateIndex] += ProductionRates::k9(vibrationalState + 1) * N2 * Q[stateIndex + 1];
88 }
89 }
90
91 // OI model production
92 // Singlet molecular oxygen in odd, non-symmetric sigma state
93 S[Shortcuts::O2cu] += (ProductionRates::ZETA * ProductionRates::k1(T) * O * O * M);
94 // Singlet atomic oxygen in excited state S
95 S[Shortcuts::OS] += (ProductionRates::DELTA * ProductionRates::k3() * O * Q[Shortcuts::O2cu]);
96
97 /*************************
98 * Loss of minor species *
99 *************************/
100 // OH model loss
101 for (int vibrationalState = 0; vibrationalState < 10; ++vibrationalState) {
102 // loss via k5 from OH(v) production
103 S[Shortcuts::H] -= ProductionRates::k5(T, vibrationalState) * H * O3;
104 S[Shortcuts::O3] -= ProductionRates::k5(T, vibrationalState) * H * O3;
105
106 const int stateIndex = Shortcuts::OH0 + vibrationalState;
107 // loss via Einstein coefficients by quenching into lower states within bandwidth
108 for (int quenchedState = vibrationalState - 1; quenchedState >= std::max(0, vibrationalState - BANDWIDTH); --quenchedState) {
109 S[stateIndex] -= EINSTEIN_COEFFICIENTS(vibrationalState, quenchedState) * Q[stateIndex];
110 }
111
112 // loss via k7 by quenching into hydrogen and molecular oxygen
113 S[stateIndex] -= ProductionRates::k7(vibrationalState) * O * Q[stateIndex];
114
115 // loss via k8 by quenching into all lower states
116 for (int quenchedState = vibrationalState - 1; quenchedState >= 0; --quenchedState) {
117 S[stateIndex] -= ProductionRates::k8(vibrationalState, quenchedState) * O2 * Q[stateIndex];
118 }
119
120 if (vibrationalState > 0) {
121 // loss via k9 by quenching into next lower vibrational state
122 S[stateIndex] -= ProductionRates::k9(vibrationalState) * N2 * Q[stateIndex];
123 }
124 }
125
126 // OI model loss
127 S[Shortcuts::O2cu] -= (ProductionRates::k2() * O2 + ProductionRates::k3() * (1 + ProductionRates::DELTA) * O + ProductionRates::A1()) * Q[Shortcuts::O2cu];
128 S[Shortcuts::OS] -= (ProductionRates::k4(T) * O2 + ProductionRates::A2() + ProductionRates::A5577()) * Q[Shortcuts::OS];
129
130 /***************************
131 * Remove initial tendency *
132 ***************************/
133 S[Shortcuts::O3] -= Q[Shortcuts::dO3dt0];
134
135 /*******************
136 * Apply threshold *
137 *******************/
138 for (int unknown = 0; unknown < NumberOfUnknowns; ++unknown) {
139 const {{COMPUTE_PRECISION}} value = S[unknown];
140 S[unknown] = (std::fabs(value) < CHEMISTRY_NUMERICAL_THRESHOLD) ? 0.0 : value;
141 }"""
142
143
145 return """
146 if (timeStamp == 0.0 and timeStepSize > 0.0) {
147 // initialize initial tendency for ozone
148 // this is copied and adapted from toolbox::blockstructured::copyUnknown()
149#if DIMENSIONS==2
150 for (int x=0; x<{{NUMBER_OF_VOLUMES_PER_AXIS}}; x++)
151 for (int y=0; y<{{NUMBER_OF_VOLUMES_PER_AXIS}}; y++) {
152 const int ozoneIndex = 3;
153 int oldQWithHaloOzoneIndex = ( x + {{HALO_SIZE}} + (y + {{HALO_SIZE}}) * ({{NUMBER_OF_VOLUMES_PER_AXIS}} + 2 * {{HALO_SIZE}}) ) * {{NUMBER_OF_UNKNOWNS + NUMBER_OF_AUXILIARY_VARIABLES}} + ozoneIndex;
154 int newQIndex = ( x + y * {{NUMBER_OF_VOLUMES_PER_AXIS}} ) * {{NUMBER_OF_UNKNOWNS + NUMBER_OF_AUXILIARY_VARIABLES}};
155 int newQOzoneIndex = newQIndex + ozoneIndex;
156 int newQOzoneInitialTendencyIndex = newQIndex + {{NUMBER_OF_UNKNOWNS + NUMBER_OF_AUXILIARY_VARIABLES}} - 1; // dO3dt0 should always be the last auxiliary variable
157 // initialize initial tendency for ozone
158 QOut[newQOzoneInitialTendencyIndex] = (QOut[newQOzoneIndex] - QIn[oldQWithHaloOzoneIndex]) / timeStepSize;
159 // set ozone change to 0, since with initial tendency removed, there should be no change in ozone
160 QOut[newQOzoneIndex] = QIn[oldQWithHaloOzoneIndex];
161 }
162#else
163 for (int x=0; x<{{NUMBER_OF_VOLUMES_PER_AXIS}}; x++)
164 for (int y=0; y<{{NUMBER_OF_VOLUMES_PER_AXIS}}; y++)
165 for (int z=0; z<{{NUMBER_OF_VOLUMES_PER_AXIS}}; z++){
166 const int ozoneIndex = 3;
167 int oldQWithHaloOzoneIndex = ( x + {{HALO_SIZE}} + (y + {{HALO_SIZE}}) * ({{NUMBER_OF_VOLUMES_PER_AXIS}} + 2 * {{HALO_SIZE}}) + (z + {{HALO_SIZE}} ) * ({{NUMBER_OF_VOLUMES_PER_AXIS}} + 2 * {{HALO_SIZE}}) * ({{NUMBER_OF_VOLUMES_PER_AXIS}} + 2 * {{HALO_SIZE}})) * {{NUMBER_OF_UNKNOWNS + NUMBER_OF_AUXILIARY_VARIABLES}} + ozoneIndex;
168 int newQIndex = ( x + y * {{NUMBER_OF_VOLUMES_PER_AXIS}} + z * {{NUMBER_OF_VOLUMES_PER_AXIS}} * {{NUMBER_OF_VOLUMES_PER_AXIS}} ) * {{NUMBER_OF_UNKNOWNS + NUMBER_OF_AUXILIARY_VARIABLES}};
169 int newQOzoneIndex = newQIndex + ozoneIndex;
170 int newQOzoneInitialTendencyIndex = newQIndex + {{NUMBER_OF_UNKNOWNS + NUMBER_OF_AUXILIARY_VARIABLES}} - 1; // dO3dt0 should always be the last auxiliary variable
171 // initialize initial tendency for ozone
172 QOut[newQOzoneInitialTendencyIndex] = (QOut[newQOzoneIndex] - QIn[oldQWithHaloOzoneIndex]) / timeStepSize;
173 // set ozone change to 0, since with initial tendency removed, there should be no change in ozone
174 QOut[newQOzoneIndex] = QIn[oldQWithHaloOzoneIndex];
175 }
176#endif
177 }
178"""
get_source_term()
Returns source term of production and loss for minor species.
Definition AirglowPDE.py:28
get_initial_tendency_postprocessing()
get_max_eigenvalue()
Definition AirglowPDE.py:1