@@ -194,8 +194,13 @@ namespace aspect
194194
195195 // Derivative terms related to the Newton solver
196196 VectorizedArray<number> deta_deps_times_sym_grad_u (0 .);
197- VectorizedArray<number> eps_times_sym_grad_u (0 .);
198197 VectorizedArray<number> deta_dp_times_p (0 .);
198+ VectorizedArray<number> eps_times_sym_grad_u (0 .);
199+ VectorizedArray<number> eps_times_sym_grad_u_JxW (0 .);
200+ VectorizedArray<number> theta_times_div_u (0 .);
201+ VectorizedArray<number> theta_times_div_u_JxW (0 .);
202+
203+ // Pre-compute the averaged values
199204 if (cell_data->enable_newton_derivatives
200205 && cell_data->average_newton_factors )
201206 {
@@ -209,7 +214,29 @@ namespace aspect
209214 * sym_grad_u;
210215 deta_dp_times_p += cell_data->newton_factor_wrt_pressure_table (cell,q) * val_p;
211216 if (cell_data->symmetrize_newton_system )
212- eps_times_sym_grad_u += cell_data->strain_rate_table (cell,q) * sym_grad_u;
217+ {
218+ // The symmetrization is more complicated than it looks:
219+ // The averaged Newton term is expressed as
220+ // 2 (\sum_q JxW_q symgrad_phi_Iq : epsilon_q) (\sum_r w_r deta_depsilon_r : symgrad_phi_Jr)
221+ // when symmetrized, it becomes
222+ // (\sum_q JxW_q symgrad_phi_Iq : epsilon_q) (\sum_r w_r deta_depsilon_r : symgrad_phi_Jr) +
223+ // (\sum_r w_r symgrad_phi_Ir : deta_depsilon_r) (\sum_q JxW_q epsilon_q : symgrad_phi_Jq)
224+ // Let us focus on the second term. In the matrix-free framework, we should submit a
225+ // symmetric tensor for each quadrature point q to be multiplied by the test function
226+ // symgrad_phi_Iq and the quadrature weight JxW_q. In order to do so, we first rewrite the
227+ // second term by swapping q and r:
228+ // \sum_q\sum_r JxW_r w_q (symgrad_phi_Iq : deta_depsilon_q) (epsilon_r : symgrad_phi_Jr)
229+ // In the above expression, the test function is separated out, but the quadrature weight
230+ // is not. To separate JxW_q, we further rewrite the second term by
231+ // \sum_q\sum_r JxW_q (JxW_r / JxW_q) w_q (symgrad_phi_Iq : deta_depsilon_q) (epsilon_r : symgrad_phi_Jr)
232+ // Thus, the term to be submitted for each quadrature point q is
233+ // \sum_r (JxW_r / JxW_q) w_q deta_depsilon_q (epsilon_r : symgrad_phi_Jr)
234+ // That is the reason why we need the term (epsilon_r : symgrad_phi_Jr) JxW_r.
235+ eps_times_sym_grad_u_JxW += cell_data->strain_rate_table (cell,q) * sym_grad_u * u_eval.JxW (q);
236+ // The same goes for the term corresponding to compressibility/dilation
237+ if (cell_data->is_compressible || cell_data->enable_prescribed_dilation )
238+ theta_times_div_u_JxW += trace (cell_data->strain_rate_table (cell,q)) * trace (sym_grad_u) * u_eval.JxW (q);
239+ }
213240 }
214241 }
215242
@@ -249,7 +276,12 @@ namespace aspect
249276 // Add the Newton derivatives if required.
250277 if (cell_data->enable_newton_derivatives )
251278 {
252- if (!cell_data->average_newton_factors )
279+ if (cell_data->average_newton_factors )
280+ {
281+ if (cell_data->symmetrize_newton_system )
282+ eps_times_sym_grad_u = eps_times_sym_grad_u_JxW / u_eval.JxW (q);
283+ }
284+ else
253285 {
254286 deta_deps_times_sym_grad_u = cell_data->newton_factor_wrt_strain_rate_table (cell,q)
255287 * sym_grad_u;
@@ -269,17 +301,22 @@ namespace aspect
269301 if (cell_data->is_compressible ||
270302 cell_data->enable_prescribed_dilation )
271303 {
272- const number one_third = 1.0 / 3.0 ;
304+ constexpr number one_third = 1.0 / 3.0 ;
273305 if (cell_data->symmetrize_newton_system )
274306 {
275- velocity_terms -= one_third * cell_data->newton_factor_wrt_strain_rate_table (cell,q) * (div_u * div_u);
307+ if (cell_data->average_newton_factors )
308+ theta_times_div_u = theta_times_div_u_JxW / u_eval.JxW (q);
309+ else
310+ theta_times_div_u = trace (cell_data->strain_rate_table (cell,q)) * div_u;
311+
312+ velocity_terms -= one_third * cell_data->newton_factor_wrt_strain_rate_table (cell,q) * theta_times_div_u;
276313 for (unsigned int d = 0 ; d < dim; ++d)
277- velocity_terms[d][d] -= one_third * div_u * deta_deps_times_sym_grad_u;
314+ velocity_terms[d][d] -= one_third * trace (cell_data-> strain_rate_table (cell,q)) * deta_deps_times_sym_grad_u;
278315 }
279316 else
280317 {
281318 for (unsigned int d = 0 ; d < dim; ++d)
282- velocity_terms[d][d] -= 2.0 * one_third * div_u * deta_deps_times_sym_grad_u;
319+ velocity_terms[d][d] -= 2.0 * one_third * trace (cell_data-> strain_rate_table (cell,q)) * deta_deps_times_sym_grad_u;
283320 }
284321
285322 if (cell_data->enable_prescribed_dilation )
0 commit comments