ryujin 2.1.1 revision 46bf70e400e423a8ffffe8300887eeb35b8dfb2c
riemann_solver.template.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2020 - 2024 by the ryujin authors
4//
5
6#pragma once
7
8#include "riemann_solver.h"
9
10#include <newton.h>
11#include <simd.h>
12
13// #define DEBUG_RIEMANN_SOLVER
14
15namespace ryujin
16{
17 namespace Euler
18 {
19 template <int dim, typename Number>
20 DEAL_II_ALWAYS_INLINE inline Number
22 const Number p_star) const
23 {
24 const auto view = hyperbolic_system.view<dim, Number>();
25 const auto &gamma = view.gamma();
26
27 const auto &[rho, u, p, a] = riemann_data;
28
29 const Number Az = ScalarNumber(2.) / (rho * (gamma + Number(1.)));
30 const Number Bz =
31 (gamma - ScalarNumber(1.)) / (gamma + ScalarNumber(1.)) * p;
32 const Number radicand = Az / (p_star + Bz);
33 const Number true_value = (p_star - p) * std::sqrt(radicand);
34
35 const auto exponent =
36 ScalarNumber(0.5) * (gamma - ScalarNumber(1.)) / gamma;
37 const Number factor = ryujin::pow(p_star / p, exponent) - Number(1.);
38 const auto false_value =
39 ScalarNumber(2.) * a * factor / (gamma - ScalarNumber(1.));
40
41 return dealii::compare_and_apply_mask<
42 dealii::SIMDComparison::greater_than_or_equal>(
43 p_star, p, true_value, false_value);
44 }
45
46
47 template <int dim, typename Number>
48 DEAL_II_ALWAYS_INLINE inline Number
50 const Number &p_star) const
51 {
52 const auto view = hyperbolic_system.view<dim, Number>();
53
55 const auto &gamma = view.gamma();
56 const auto &gamma_inverse = view.gamma_inverse();
57 const auto &gamma_minus_one_inverse = view.gamma_minus_one_inverse();
58 const auto &gamma_plus_one_inverse = view.gamma_plus_one_inverse();
59
60 const auto &[rho, u, p, a] = riemann_data;
61
62 const Number radicand_inverse = ScalarNumber(0.5) * rho *
63 ((gamma + ScalarNumber(1.)) * p_star +
64 (gamma - ScalarNumber(1.)) * p);
65 const Number denominator =
66 (p_star + (gamma - ScalarNumber(1.)) * gamma_plus_one_inverse * p);
67 const Number true_value =
68 (denominator - ScalarNumber(0.5) * (p_star - p)) /
69 (denominator * std::sqrt(radicand_inverse));
70
71 const auto exponent =
72 (ScalarNumber(-1.) - gamma) * ScalarNumber(0.5) * gamma_inverse;
73 const Number factor = (gamma - ScalarNumber(1.)) * ScalarNumber(0.5) *
74 gamma_inverse * ryujin::pow(p_star / p, exponent) /
75 p;
76 const auto false_value =
77 factor * ScalarNumber(2.) * a * gamma_minus_one_inverse;
78
79 return dealii::compare_and_apply_mask<
80 dealii::SIMDComparison::greater_than_or_equal>(
81 p_star, p, true_value, false_value);
82 }
83
84
85 template <int dim, typename Number>
86 DEAL_II_ALWAYS_INLINE inline Number
88 const primitive_type &riemann_data_j,
89 const Number p_in) const
90 {
91 const Number &u_i = riemann_data_i[1];
92 const Number &u_j = riemann_data_j[1];
93
94 return f(riemann_data_i, p_in) + f(riemann_data_j, p_in) + u_j - u_i;
95 }
96
97
98 template <int dim, typename Number>
99 DEAL_II_ALWAYS_INLINE inline Number
101 const primitive_type &riemann_data_j,
102 const Number &p) const
103 {
104 return df(riemann_data_i, p) + df(riemann_data_j, p);
105 }
106
107
108 /*
109 * The approximate Riemann solver is based on a function phi(p) that is
110 * montone increasing in p, concave down and whose (weak) third
111 * derivative is non-negative and locally bounded [1, p. 912]. Because we
112 * actually do not perform any iteration for computing our wavespeed
113 * estimate we can get away by only implementing a specialized variant of
114 * the phi function that computes phi(p_max). It inlines the
115 * implementation of the "f" function and eliminates all unnecessary
116 * branches in "f".
117 *
118 * Cost: 0x pow, 2x division, 2x sqrt
119 */
120 template <int dim, typename Number>
121 DEAL_II_ALWAYS_INLINE inline Number
123 const primitive_type &riemann_data_i,
124 const primitive_type &riemann_data_j) const
125 {
126 const auto view = hyperbolic_system.view<dim, Number>();
127 const auto &gamma = view.gamma();
128
129 const auto &[rho_i, u_i, p_i, a_i] = riemann_data_i;
130 const auto &[rho_j, u_j, p_j, a_j] = riemann_data_j;
131
132 const Number p_max = std::max(p_i, p_j);
133
134 const Number radicand_inverse_i = ScalarNumber(0.5) * rho_i *
135 ((gamma + ScalarNumber(1.)) * p_max +
136 (gamma - ScalarNumber(1.)) * p_i);
137
138 const Number value_i = (p_max - p_i) / std::sqrt(radicand_inverse_i);
139
140 const Number radicand_inverse_j = ScalarNumber(0.5) * rho_j *
141 ((gamma + ScalarNumber(1.)) * p_max +
142 (gamma - ScalarNumber(1.)) * p_j);
143
144 const Number value_j = (p_max - p_j) / std::sqrt(radicand_inverse_j);
145
146 return value_i + value_j + u_j - u_i;
147 }
148
149
150 /*
151 * Next we construct approximations for the two extreme wave speeds of
152 * the Riemann fan [1, p. 912, (3.7) + (3.8)] and compute an upper bound
153 * lambda_max of the maximal wave speed:
154 */
155
156
157 /*
158 * see [1], page 912, (3.7)
159 *
160 * Cost: 0x pow, 1x division, 1x sqrt
161 */
162 template <int dim, typename Number>
163 DEAL_II_ALWAYS_INLINE inline Number
165 const primitive_type &riemann_data, const Number p_star) const
166 {
167 const auto view = hyperbolic_system.view<dim, Number>();
168 const auto &gamma = view.gamma();
169 const auto &gamma_inverse = view.gamma_inverse();
170 const auto factor =
171 (gamma + ScalarNumber(1.0)) * ScalarNumber(0.5) * gamma_inverse;
172
173 const auto &[rho, u, p, a] = riemann_data;
174 const auto inv_p = ScalarNumber(1.0) / p;
175
176 const Number tmp = positive_part((p_star - p) * inv_p);
177
178 return u - a * std::sqrt(ScalarNumber(1.0) + factor * tmp);
179 }
180
181
182 /*
183 * see [1], page 912, (3.8)
184 *
185 * Cost: 0x pow, 1x division, 1x sqrt
186 */
187 template <int dim, typename Number>
188 DEAL_II_ALWAYS_INLINE inline Number
190 const primitive_type &primitive_state, const Number p_star) const
191 {
192 const auto view = hyperbolic_system.view<dim, Number>();
193 const auto &gamma = view.gamma();
194 const auto &gamma_inverse = view.gamma_inverse();
195 const Number factor =
196 (gamma + ScalarNumber(1.0)) * ScalarNumber(0.5) * gamma_inverse;
197
198 const auto &[rho, u, p, a] = primitive_state;
199 const auto inv_p = ScalarNumber(1.0) / p;
200
201 const Number tmp = positive_part((p_star - p) * inv_p);
202 return u + a * std::sqrt(Number(1.0) + factor * tmp);
203 }
204
205
215 template <int dim, typename Number>
216 DEAL_II_ALWAYS_INLINE inline std::array<Number, 2>
218 const std::array<Number, 4> &riemann_data_i,
219 const std::array<Number, 4> &riemann_data_j,
220 const Number p_1,
221 const Number p_2) const
222 {
223 const Number nu_11 = lambda1_minus(riemann_data_i, p_2 /*SIC!*/);
224 const Number nu_12 = lambda1_minus(riemann_data_i, p_1 /*SIC!*/);
225
226 const Number nu_31 = lambda3_plus(riemann_data_j, p_1);
227 const Number nu_32 = lambda3_plus(riemann_data_j, p_2);
228
229 const Number lambda_max =
230 std::max(positive_part(nu_32), negative_part(nu_11));
231
232 const Number gap =
233 std::max(std::abs(nu_32 - nu_31), std::abs(nu_12 - nu_11));
234
235 return {{gap, lambda_max}};
236 }
237
238
239 /*
240 * For two given primitive states <code>riemann_data_i</code> and
241 * <code>riemann_data_j</code>, and a guess p_2, compute an upper bound
242 * for lambda.
243 *
244 * This is the same lambda_max as computed by compute_gap. The function
245 * simply avoids a number of unnecessary computations (in case we do
246 * not need to know the gap).
247 *
248 * Cost: 0x pow, 2x division, 2x sqrt
249 */
250 template <int dim, typename Number>
251 DEAL_II_ALWAYS_INLINE inline Number
253 const primitive_type &riemann_data_i,
254 const primitive_type &riemann_data_j,
255 const Number p_star) const
256 {
257 const Number nu_11 = lambda1_minus(riemann_data_i, p_star);
258 const Number nu_32 = lambda3_plus(riemann_data_j, p_star);
259
260 return std::max(positive_part(nu_32), negative_part(nu_11));
261 }
262
263
264 /*
265 * Two-rarefaction approximation to p_star computed for two primitive
266 * states <code>riemann_data_i</code> and <code>riemann_data_j</code>.
267 *
268 * See [1], page 914, (4.3)
269 *
270 * Cost: 2x pow, 2x division, 0x sqrt
271 */
272 template <int dim, typename Number>
273 DEAL_II_ALWAYS_INLINE inline Number
275 const primitive_type &riemann_data_i,
276 const primitive_type &riemann_data_j) const
277 {
278 const auto view = hyperbolic_system.view<dim, Number>();
279 const auto &gamma = view.gamma();
280 const auto &gamma_inverse = view.gamma_inverse();
281 const auto &gamma_minus_one_inverse = view.gamma_minus_one_inverse();
282
283 const auto &[rho_i, u_i, p_i, a_i] = riemann_data_i;
284 const auto &[rho_j, u_j, p_j, a_j] = riemann_data_j;
285 const auto inv_p_j = ScalarNumber(1.) / p_j;
286
287 /*
288 * Nota bene (cf. [1, (4.3)]):
289 * a_Z^0 * sqrt(1 - b * rho_Z) = a_Z * (1 - b * rho_Z)
290 * We have computed a_Z already, so we are simply going to use this
291 * identity below:
292 */
293
294 const auto factor = (gamma - ScalarNumber(1.)) * ScalarNumber(0.5);
295
296 /*
297 * Nota bene (cf. [1, (3.6)]: The condition "numerator > 0" is the
298 * well-known non-vacuum condition. In case we encounter numerator <= 0
299 * then p_star = 0 is the correct pressure to compute the wave speed.
300 * Therefore, all we have to do is to take the positive part of the
301 * expression:
302 */
303
304 const Number numerator = positive_part(a_i + a_j - factor * (u_j - u_i));
305 const Number denominator =
306 a_i * ryujin::pow(p_i * inv_p_j, -factor * gamma_inverse) + a_j;
307
308 const auto exponent = ScalarNumber(2.0) * gamma * gamma_minus_one_inverse;
309
310 const auto p_1_tilde =
311 p_j * ryujin::pow(numerator / denominator, exponent);
312
313#ifdef DEBUG_RIEMANN_SOLVER
314 std::cout << "p_star_two_rarefaction = " << p_1_tilde << std::endl;
315#endif
316 return p_1_tilde;
317 }
318
319
320 /*
321 * Failsafe approximation to p_star computed for two primitive
322 * states <code>riemann_data_i</code> and <code>riemann_data_j</code>.
323 *
324 * See [1], page 914, (4.3)
325 *
326 * Cost: 2x pow, 2x division, 0x sqrt
327 */
328 template <int dim, typename Number>
329 DEAL_II_ALWAYS_INLINE inline Number
331 const primitive_type &riemann_data_i,
332 const primitive_type &riemann_data_j) const
333 {
334 const auto view = hyperbolic_system.view<dim, Number>();
335 const auto &gamma = view.gamma();
336
337 const auto &[rho_i, u_i, p_i, a_i] = riemann_data_i;
338 const auto &[rho_j, u_j, p_j, a_j] = riemann_data_j;
339
340 /*
341 * Compute (5.11) formula for \tilde p_2^\ast:
342 *
343 * Cost: 0x pow, 3x division, 3x sqrt
344 */
345
346 const Number p_max = std::max(p_i, p_j);
347
348 Number radicand_i = ScalarNumber(2.) * p_max;
349 radicand_i /=
350 rho_i * ((gamma + Number(1.)) * p_max + (gamma - Number(1.)) * p_i);
351
352 const Number x_i = std::sqrt(radicand_i);
353
354 Number radicand_j = ScalarNumber(2.) * p_max;
355 radicand_j /=
356 rho_j * ((gamma + Number(1.)) * p_max + (gamma - Number(1.)) * p_j);
357
358 const Number x_j = std::sqrt(radicand_j);
359
360 const Number a = x_i + x_j;
361 const Number b = u_j - u_i;
362 const Number c = -p_i * x_i - p_j * x_j;
363
364 const Number base = (-b + std::sqrt(b * b - ScalarNumber(4.) * a * c)) /
365 (ScalarNumber(2.) * a);
366 const Number p_2_tilde = base * base;
367
368#ifdef DEBUG_RIEMANN_SOLVER
369 std::cout << "p_star_failsafe = " << p_2_tilde << std::endl;
370#endif
371 return p_2_tilde;
372 }
373
374
375 template <int dim, typename Number>
376 DEAL_II_ALWAYS_INLINE inline auto
378 const state_type &U, const dealii::Tensor<1, dim, Number> &n_ij) const
380 {
381 const auto view = hyperbolic_system.view<dim, Number>();
382
383 const auto rho = view.density(U);
384 const auto rho_inverse = Number(1.0) / rho;
385
386 const auto m = view.momentum(U);
387 const auto proj_m = n_ij * m;
388 const auto perp = m - proj_m * n_ij;
389
390 const auto E =
391 view.total_energy(U) - Number(0.5) * perp.norm_square() * rho_inverse;
392
393 using state_type_1d =
395 const auto view_1d = hyperbolic_system.view<1, Number>();
396
397 const auto state = state_type_1d{{rho, proj_m, E}};
398 const auto p = view_1d.pressure(state);
399 const auto a = view_1d.speed_of_sound(state);
400 return {{rho, proj_m * rho_inverse, p, a}};
401 }
402
403
404 template <int dim, typename Number>
406 const primitive_type &riemann_data_i,
407 const primitive_type &riemann_data_j) const
408 {
409 /*
410 * For exactly solving the Riemann problem we need to start with a
411 * good upper and lower bound, p_1 <= p_star <= p_2, for finding
412 * phi(p_star) == 0. This implies that we have to ensure that
413 * phi(p_2) >= 0 and phi(p_1) <= 0.
414 *
415 * Instead of solving the Riemann problem exactly, however we will
416 * simply use the upper bound p_2 (with p_2 >= p_star) to compute
417 * lambda_max and return the estimate.
418 *
419 * We will use three candidates, p_min, p_max and the two rarefaction
420 * approximation p_star_tilde. We have (up to round-off errors) that
421 * phi(p_star_tilde) >= 0. So this is a safe upper bound, it might
422 * just be too large.
423 *
424 * Depending on the sign of phi(p_max) we select the following ranges:
425 *
426 * phi(p_max) < 0:
427 * p_1 <- p_max and p_2 <- p_star_tilde
428 *
429 * phi(p_max) >= 0:
430 * p_1 <- p_min and p_2 <- min(p_max, p_star_tilde)
431 *
432 * Nota bene:
433 *
434 * - The special case phi(p_max) == 0 as discussed in [1] is already
435 * contained in the second condition.
436 *
437 * - In principle, we would have to treat the case phi(p_min) > 0 as
438 * well. This corresponds to two expansion waves and a good
439 * estimate for the wavespeed is obtained by simply computing
440 * lambda_max with p_2 = 0.
441 *
442 * However, it turns out that numerically in this case we will
443 * have
444 *
445 * 0 < p_star <= p_star_tilde <= p_min <= p_max.
446 *
447 * So it is sufficient to end up with p_2 = p_star_tilde (!!) to
448 * compute the exact same wave speed as for p_2 = 0.
449 *
450 * Note: If for some reason p_star should be computed exactly,
451 * then p_1 has to be set to zero. This can be done efficiently by
452 * simply checking for p_2 < p_1 and setting p_1 <- 0 if
453 * necessary.
454 */
455
456 const auto &[rho_i, u_i, p_i, a_i] = riemann_data_i;
457 const auto &[rho_j, u_j, p_j, a_j] = riemann_data_j;
458
459#ifdef DEBUG_RIEMANN_SOLVER
460 std::cout << "rho_left: " << rho_i << std::endl;
461 std::cout << "u_left: " << u_i << std::endl;
462 std::cout << "p_left: " << p_i << std::endl;
463 std::cout << "a_left: " << a_i << std::endl;
464 std::cout << "rho_right: " << rho_j << std::endl;
465 std::cout << "u_right: " << u_j << std::endl;
466 std::cout << "p_right: " << p_j << std::endl;
467 std::cout << "a_right: " << a_j << std::endl;
468#endif
469
470 const Number p_max = std::max(p_i, p_j);
471
472 const Number rarefaction =
473 p_star_two_rarefaction(riemann_data_i, riemann_data_j);
474 const Number failsafe = p_star_failsafe(riemann_data_i, riemann_data_j);
475 const Number p_star_tilde = std::min(rarefaction, failsafe);
476
477 const Number phi_p_max = phi_of_p_max(riemann_data_i, riemann_data_j);
478
479 Number p_2 =
480 dealii::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
481 phi_p_max,
482 Number(0.),
483 p_star_tilde,
484 std::min(p_max, p_star_tilde));
485
486#ifdef DEBUG_RIEMANN_SOLVER
487 std::cout << " p^*_tilde = " << p_2 << "\n";
488 std::cout << " phi(p_*_t) = "
489 << phi(riemann_data_i, riemann_data_j, p_2) << std::endl;
490#endif
491
492 /*
493 * If we do no Newton iteration, cut it short:
494 */
495
496 if (parameters.newton_max_iterations() == 0) {
497 const auto lambda_max =
498 compute_lambda(riemann_data_i, riemann_data_j, p_2);
499
500#ifdef DEBUG_RIEMANN_SOLVER
501 std::cout << "-> lambda_max = " << lambda_max << std::endl;
502#endif
503 return lambda_max;
504 }
505
506 /*
507 * Compute p_1 and ensure that p_1 < p_2. If we hit a case with two
508 * expansions we might indeed have that p_star_tilde < p_1. Set p_1 =
509 * p_2 in this case.
510 */
511
512 const Number p_min = std::min(riemann_data_i[2], riemann_data_j[2]);
513
514 Number p_1 =
515 dealii::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
516 phi_p_max, Number(0.), p_max, p_min);
517
518 p_1 = dealii::compare_and_apply_mask<
519 dealii::SIMDComparison::less_than_or_equal>(p_1, p_2, p_1, p_2);
520
521 /*
522 * Step 2: Perform quadratic Newton iteration.
523 *
524 * See [1], p. 915f (4.8) and (4.9)
525 */
526
527 auto [gap, lambda_max] =
528 compute_gap(riemann_data_i, riemann_data_j, p_1, p_2);
529
530#ifdef DEBUG_RIEMANN_SOLVER
531 std::cout << std::fixed << std::setprecision(16);
532 std::cout << "p_1: (start) " << p_1 << std::endl;
533 std::cout << "p_2: (start) " << p_2 << std::endl;
534 std::cout << "gap: (start) " << gap << std::endl;
535 std::cout << "l_m: (start) " << lambda_max << std::endl;
536#endif
537
538 for (unsigned int i = 0; i < parameters.newton_max_iterations(); ++i) {
539
540 /* We accept our current guess if we reach the tolerance... */
541 const Number tolerance(parameters.newton_tolerance());
542 if (std::max(Number(0.), gap - tolerance) == Number(0.)) {
543#ifdef DEBUG_RIEMANN_SOLVER
544 std::cout << "converged after " << i << " iterations." << std::endl;
545#endif
546 break;
547 }
548
549 // FIXME: Fuse these computations:
550 const Number phi_p_1 = phi(riemann_data_i, riemann_data_j, p_1);
551 const Number phi_p_2 = phi(riemann_data_i, riemann_data_j, p_2);
552 const Number dphi_p_1 = dphi(riemann_data_i, riemann_data_j, p_1);
553 const Number dphi_p_2 = dphi(riemann_data_i, riemann_data_j, p_2);
554
555 quadratic_newton_step(p_1, p_2, phi_p_1, phi_p_2, dphi_p_1, dphi_p_2);
556
557 /* Update lambda_max and gap: */
558 auto [gap_new, lambda_max_new] =
559 compute_gap(riemann_data_i, riemann_data_j, p_1, p_2);
560 gap = gap_new;
561 lambda_max = lambda_max_new;
562
563#ifdef DEBUG_RIEMANN_SOLVER
564 std::cout << "phi_p_1: " << phi_p_1 << std::endl;
565 std::cout << "phi_p_2: " << phi_p_2 << std::endl;
566 std::cout << "dphi_p_1: " << dphi_p_1 << std::endl;
567 std::cout << "dphi_p_2: " << dphi_p_2 << std::endl;
568 std::cout << "p_1: ( " << i << " ) " << p_1 << std::endl;
569 std::cout << "p_2: ( " << i << " ) " << p_2 << std::endl;
570 std::cout << "gap: " << gap << std::endl;
571 std::cout << "l_m: " << lambda_max << std::endl;
572#endif
573 }
574
575#ifdef DEBUG_RIEMANN_SOLVER
576 std::cout << "-> lambda_max = " << lambda_max << std::endl;
577#endif
578
579 return lambda_max;
580 }
581
582
583 template <int dim, typename Number>
584 DEAL_II_ALWAYS_INLINE inline Number RiemannSolver<dim, Number>::compute(
585 const state_type &U_i,
586 const state_type &U_j,
587 const unsigned int /*i*/,
588 const unsigned int * /*js*/,
589 const dealii::Tensor<1, dim, Number> &n_ij) const
590 {
591 const auto riemann_data_i = riemann_data_from_state(U_i, n_ij);
592 const auto riemann_data_j = riemann_data_from_state(U_j, n_ij);
593
594 return compute(riemann_data_i, riemann_data_j);
595 }
596
597 } // namespace Euler
598} // namespace ryujin
dealii::Tensor< 1, problem_dimension, Number > state_type
Number phi_of_p_max(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
Number compute_lambda(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number p_star) const
typename View::ScalarNumber ScalarNumber
Number df(const primitive_type &riemann_data, const Number &p_star) const
Number lambda1_minus(const primitive_type &riemann_data, const Number p_star) const
Number phi(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number p_in) const
Number p_star_two_rarefaction(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
primitive_type riemann_data_from_state(const state_type &U, const dealii::Tensor< 1, dim, Number > &n_ij) const
std::array< Number, 2 > compute_gap(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number p_1, const Number p_2) const
typename View::state_type state_type
Number compute(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
std::array< Number, riemann_data_size > primitive_type
Number p_star_failsafe(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
Number dphi(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number &p) const
Number f(const primitive_type &riemann_data, const Number p_star) const
Number lambda3_plus(const primitive_type &primitive_state, const Number p_star) const
T pow(const T x, const T b)
DEAL_II_ALWAYS_INLINE Number negative_part(const Number number)
Definition: simd.h:125
DEAL_II_ALWAYS_INLINE Number positive_part(const Number number)
Definition: simd.h:113
DEAL_II_ALWAYS_INLINE void quadratic_newton_step(Number &p_1, Number &p_2, const Number phi_p_1, const Number phi_p_2, const Number dphi_p_1, const Number dphi_p_2, const Number sign=Number(1.0))
Definition: newton.h:39