Skip to content

Commit 0810c7e

Browse files
committed
fix bugs in the Newton derivatives in GMG solver
1 parent ffe3dfb commit 0810c7e

File tree

1 file changed

+44
-7
lines changed

1 file changed

+44
-7
lines changed

source/simulator/solver/matrix_free_operators.cc

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)