44 return elem_pt->
ndof();
83 const unsigned& ieqn_local)
127 double*
const& parameter_pt,
140 double*
const& parameter_pt,
170 std::ostringstream error_stream;
171 error_stream <<
"There is no bifurcation parameter associated with the "
172 "current assembly handler.\n"
173 <<
"Eigenfunction are only calculated by the Fold, PitchFork "
178 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
190 std::ostringstream error_stream;
191 error_stream <<
"There is no eigenfunction associated with the current "
192 "assembly handler.\n"
193 <<
"Eigenfunction are only calculated by the Fold, PitchFork "
198 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
208 Vector<std::pair<unsigned, unsigned>>
const& history_index,
241 return elem_pt->
ndof();
285 if (matrix.size() != 1)
287 throw OomphLibError(
"ExplicitTimeSteps should return one matrix",
288 OOMPH_CURRENT_FUNCTION,
289 OOMPH_EXCEPTION_LOCATION);
308 return elem_pt->
ndof();
328 "An eigenproblem does not have a get_residuals function",
329 OOMPH_CURRENT_FUNCTION,
330 OOMPH_EXCEPTION_LOCATION);
340 throw OomphLibError(
"An eigenproblem does not have a get_jacobian function",
341 OOMPH_CURRENT_FUNCTION,
342 OOMPH_EXCEPTION_LOCATION);
357 if (matrix.size() != 2)
359 throw OomphLibError(
"EigenProblems should return two matrices",
360 OOMPH_CURRENT_FUNCTION,
361 OOMPH_EXCEPTION_LOCATION);
365 unsigned n_var = elem_pt->
ndof();
375 for (
unsigned i = 0;
i < n_var;
i++)
377 for (
unsigned j = 0; j < n_var; j++)
414 throw OomphLibError(
"The result vector must not be distributed",
415 OOMPH_CURRENT_FUNCTION,
416 OOMPH_EXCEPTION_LOCATION);
429 unsigned n_dof = problem_pt->
ndof();
464 for (
unsigned n = 0; n < (n_dof - 1); ++n)
466 y[n] = handler_pt->
Y[n];
477 for (
unsigned long e = 0;
e < n_element;
e++)
481 unsigned n_var = elem_pt->
ndof();
490 for (
unsigned n = 0; n < n_var; n++)
493 for (
unsigned m = 0; m < n_var; m++)
496 Jy[eqn_number] += jac(n, m) * y[unknown];
507 for (
unsigned n = 0; n < n_dof; n++)
509 y_minus_alpha[n] = y[n] - (*Alpha_pt)[n];
514 double dof_length = 0.0, a_length = 0.0, alpha_length = 0.0;
515 for (
unsigned n = 0; n < n_dof; n++)
517 if (std::fabs(problem_pt->
dof(n)) > dof_length)
519 dof_length = std::fabs(problem_pt->
dof(n));
521 if (std::fabs(a[n]) > a_length)
523 a_length = std::fabs(a[n]);
525 if (std::fabs(y_minus_alpha[n]) > alpha_length)
527 alpha_length = std::fabs(y_minus_alpha[n]);
531 double a_mult = dof_length / a_length;
532 double alpha_mult = dof_length / alpha_length;
544 for (
unsigned long e = 0;
e < n_element;
e++)
548 unsigned n_var = handler_pt->
ndof(elem_pt);
559 for (
unsigned n = 0; n < n_var; n++)
561 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
562 dof_bac[n] = problem_pt->
dof(eqn_number);
564 problem_pt->
dof(eqn_number) += a_mult * a[eqn_number];
570 handler_pt->
get_jacobian(elem_pt, res_elemental, jac_a);
573 for (
unsigned n = 0; n < n_var; n++)
575 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
576 problem_pt->
dof(eqn_number) = dof_bac[n];
578 problem_pt->
dof(eqn_number) += alpha_mult * y_minus_alpha[eqn_number];
584 handler_pt->
get_jacobian(elem_pt, res_elemental, jac_alpha);
587 for (
unsigned n = 0; n < n_var; n++)
589 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
590 problem_pt->
dof(eqn_number) = dof_bac[n];
598 for (
unsigned n = 0; n < (n_var - 1); n++)
600 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
601 double prod_a = 0.0, prod_alpha = 0.0;
602 for (
unsigned m = 0; m < (n_var - 1); m++)
604 unsigned unknown = handler_pt->
eqn_number(elem_pt, m);
605 prod_a += (jac_a(n, m) - jac(n, m)) * y[unknown];
606 prod_alpha += (jac_alpha(n, m) - jac(n, m)) * y[unknown];
608 Jprod_a[eqn_number] += prod_a / a_mult;
609 Jprod_alpha[eqn_number] += prod_alpha / alpha_mult;
613 Jprod_alpha[n_dof - 1] = 0.0;
614 Jprod_a[n_dof - 1] = 0.0;
619 for (
unsigned n = 0; n < n_dof - 1; n++)
621 b[n] = result[n_dof + n] - Jprod_a[n];
624 b[n_dof - 1] = result[n_dof - 1];
637 const double e_final = (*E_pt)[n_dof - 1];
639 const double d_final = f[n_dof - 1] / e_final;
641 for (
unsigned n = 0; n < n_dof - 1; n++)
643 result[n] = a[n] - (*Alpha_pt)[n] * d_final + d_final * y[n];
644 result[n_dof + n] = f[n] - (*E_pt)[n] * d_final;
647 result[n_dof - 1] = a[n_dof - 1] - (*Alpha_pt)[n_dof - 1] * d_final;
651 static_cast<int>(std::fabs(e_final) / e_final);
683 throw OomphLibError(
"The required vectors have not been stored",
684 OOMPH_CURRENT_FUNCTION,
685 OOMPH_EXCEPTION_LOCATION);
698 unsigned n_dof = problem_pt->
ndof();
706 throw OomphLibError(
"The result vector must not be distributed",
707 OOMPH_CURRENT_FUNCTION,
708 OOMPH_EXCEPTION_LOCATION);
715 OOMPH_CURRENT_FUNCTION,
716 OOMPH_EXCEPTION_LOCATION);
731 for (
unsigned n = 0; n < (n_dof - 1); n++)
749 double dof_length = 0.0, a_length = 0.0;
750 for (
unsigned n = 0; n < n_dof; n++)
752 if (std::fabs(problem_pt->
dof(n)) > dof_length)
754 dof_length = std::fabs(problem_pt->
dof(n));
757 if (std::fabs(a[n]) > a_length)
759 a_length = std::fabs(a[n]);
762 double a_mult = dof_length / a_length;
770 for (
unsigned long e = 0;
e < n_element;
e++)
774 unsigned n_var = handler_pt->
ndof(elem_pt);
785 for (
unsigned n = 0; n < n_var; n++)
787 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
788 dof_bac[n] = problem_pt->
dof(eqn_number);
790 problem_pt->
dof(eqn_number) += a_mult * a[eqn_number];
796 handler_pt->
get_jacobian(elem_pt, res_elemental, jac_a);
799 for (
unsigned n = 0; n < n_var; n++)
801 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
802 problem_pt->
dof(eqn_number) = dof_bac[n];
808 for (
unsigned n = 0; n < (n_var - 1); n++)
810 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
812 for (
unsigned m = 0; m < (n_var - 1); m++)
814 unsigned unknown = handler_pt->
eqn_number(elem_pt, m);
815 prod_a += (jac_a(n, m) - jac(n, m)) * handler_pt->
Y[unknown];
817 Jprod_a[eqn_number] += prod_a / a_mult;
821 Jprod_a[n_dof - 1] = 0.0;
824 for (
unsigned n = 0; n < n_dof - 1; n++)
826 b[n] = rhs[n_dof + n] - Jprod_a[n];
830 b[n_dof - 1] = rhs[n_dof - 1];
837 const double d_final = f[n_dof - 1] / (*E_pt)[n_dof - 1];
839 for (
unsigned n = 0; n < n_dof - 1; n++)
841 result[n] = a[n] - (*Alpha_pt)[n] * d_final + d_final * handler_pt->
Y[n];
842 result[n_dof + n] = f[n] - (*E_pt)[n] * d_final;
845 result[n_dof - 1] = a[n_dof - 1] - (*Alpha_pt)[n_dof - 1] * d_final;
865 double*
const& parameter_pt)
866 : Solve_which_system(Full_augmented), Parameter_pt(parameter_pt)
885 for (
unsigned e = 0;
e < n_element;
e++)
889 unsigned n_var = elem_pt->
ndof();
890 for (
unsigned n = 0; n < n_var; n++)
915 linear_solver_pt->
solve(problem_pt, x);
926 linear_solver_pt->
resolve(input_x, x);
939 problem_pt->
Dof_pt.push_back(parameter_pt);
944 for (
unsigned n = 0; n <
Ndof; n++)
946 length += x[n] * x[n];
948 length = sqrt(length);
952 for (
unsigned n = 0; n <
Ndof; n++)
954 problem_pt->
Dof_pt.push_back(&
Y[n]);
955 Y[n] =
Phi[n] = -x[n] / length;
971 double*
const& parameter_pt,
973 : Solve_which_system(Full_augmented), Parameter_pt(parameter_pt)
992 for (
unsigned e = 0;
e < n_element;
e++)
996 unsigned n_var = elem_pt->
ndof();
997 for (
unsigned n = 0; n < n_var; n++)
1005 problem_pt->
Dof_pt.push_back(parameter_pt);
1009 double length = 0.0;
1010 for (
unsigned n = 0; n <
Ndof; n++)
1012 length += eigenvector[n] * eigenvector[n];
1014 length = sqrt(length);
1018 for (
unsigned n = 0; n <
Ndof; n++)
1020 problem_pt->
Dof_pt.push_back(&
Y[n]);
1021 Y[n] =
Phi[n] = eigenvector[n] / length;
1037 double*
const& parameter_pt,
1040 : Solve_which_system(Full_augmented), Parameter_pt(parameter_pt)
1059 for (
unsigned e = 0;
e < n_element;
e++)
1063 unsigned n_var = elem_pt->
ndof();
1064 for (
unsigned n = 0; n < n_var; n++)
1072 problem_pt->
Dof_pt.push_back(parameter_pt);
1076 double length = 0.0;
1077 for (
unsigned n = 0; n <
Ndof; n++)
1079 length += eigenvector[n] * normalisation[n];
1081 length = sqrt(length);
1085 for (
unsigned n = 0; n <
Ndof; n++)
1087 problem_pt->
Dof_pt.push_back(&
Y[n]);
1088 Y[n] = eigenvector[n] / length;
1089 Phi[n] = normalisation[n];
1107 unsigned raw_ndof = elem_pt->
ndof();
1112 return (2 * raw_ndof + 1);
1116 return (raw_ndof + 1);
1124 std::ostringstream error_stream;
1126 <<
"The Solve_which_system flag can only take values 0, 1, 2"
1129 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1139 const unsigned& ieqn_local)
1142 unsigned raw_ndof = elem_pt->
ndof();
1144 unsigned long global_eqn = 0;
1146 if (ieqn_local < raw_ndof)
1148 global_eqn = elem_pt->
eqn_number(ieqn_local);
1152 else if (ieqn_local == raw_ndof)
1161 global_eqn =
Ndof + 1 + elem_pt->
eqn_number(ieqn_local - 1 - raw_ndof);
1175 unsigned raw_ndof = elem_pt->
ndof();
1195 residuals[raw_ndof] = 0.0;
1211 for (
unsigned i = 0;
i < raw_ndof;
i++)
1213 residuals[raw_ndof + 1 +
i] = 0.0;
1214 for (
unsigned j = 0; j < raw_ndof; j++)
1216 residuals[raw_ndof + 1 +
i] +=
1223 residuals[raw_ndof] +=
1224 (
Phi[global_eqn] *
Y[global_eqn]) /
Count[global_eqn];
1230 std::ostringstream error_stream;
1232 <<
"The Solve_which_system flag can only take values 0, 1, 2"
1235 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1249 unsigned augmented_ndof =
ndof(elem_pt);
1251 unsigned raw_ndof = elem_pt->
ndof();
1275 const double FD_step = 1.0e-8;
1280 double init = *unknown_pt;
1291 for (
unsigned n = 0; n < raw_ndof; n++)
1293 jacobian(n, augmented_ndof - 1) =
1294 (newres[n] - residuals[n]) /
FD_step;
1304 for (
unsigned n = 0; n < raw_ndof; n++)
1307 jacobian(augmented_ndof - 1, n) =
Phi[local_eqn] /
Count[local_eqn];
1325 for (
unsigned n = 0; n < raw_ndof; n++)
1327 for (
unsigned m = 0; m < raw_ndof; m++)
1329 jacobian(raw_ndof + 1 + n, raw_ndof + 1 + m) = jacobian(n, m);
1334 const double FD_step = 1.0e-8;
1339 double init = *unknown_pt;
1349 for (
unsigned n = 0; n < raw_ndof; n++)
1351 jacobian(n, raw_ndof) = (newres[n] - residuals[n]) /
FD_step;
1354 for (
unsigned l = 0; l < raw_ndof; l++)
1356 jacobian(raw_ndof + 1 + n, raw_ndof) +=
1357 (newjac(n, l) - jacobian(n, l)) *
Y[elem_pt->
eqn_number(l)] /
1370 for (
unsigned n = 0; n < raw_ndof; n++)
1372 unsigned long global_eqn =
eqn_number(elem_pt, n);
1375 double init = *unknown_pt;
1383 for (
unsigned k = 0; k < raw_ndof; k++)
1386 for (
unsigned l = 0; l < raw_ndof; l++)
1388 jacobian(raw_ndof + 1 + k, n) +=
1389 (newjac(k, l) - jacobian(k, l)) *
Y[elem_pt->
eqn_number(l)] /
1399 for (
unsigned n = 0; n < raw_ndof; n++)
1401 unsigned global_eqn = elem_pt->
eqn_number(n);
1402 jacobian(raw_ndof, raw_ndof + 1 + n) =
1403 Phi[global_eqn] /
Count[global_eqn];
1428 std::ostringstream error_stream;
1430 <<
"The Solve_which_system flag can only take values 0, 1, 2"
1433 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1444 double*
const& parameter_pt,
1448 unsigned raw_ndof = elem_pt->
ndof();
1468 dres_dparam[raw_ndof] = 0.0;
1478 parameter_pt, dres_dparam, djac_dparam);
1481 dres_dparam[raw_ndof] = 0.0;
1484 for (
unsigned i = 0;
i < raw_ndof;
i++)
1486 dres_dparam[raw_ndof + 1 +
i] = 0.0;
1487 for (
unsigned j = 0; j < raw_ndof; j++)
1489 dres_dparam[raw_ndof + 1 +
i] +=
1497 std::ostringstream error_stream;
1499 <<
"The Solve_which_system flag can only take values 0, 1, 2"
1502 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1513 double*
const& parameter_pt,
1517 std::ostringstream error_stream;
1519 <<
"This function has not been implemented because it is not required\n";
1520 error_stream <<
"in standard problems.\n";
1522 <<
"If you find that you need it, you will have to implement it!\n\n";
1525 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1539 std::ostringstream error_stream;
1541 <<
"This function has not been implemented because it is not required\n";
1542 error_stream <<
"in standard problems.\n";
1544 <<
"If you find that you need it, you will have to implement it!\n\n";
1547 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1558 eigenfunction.resize(1);
1561 eigenfunction[0].build(&dist, 0.0);
1563 for (
unsigned n = 0; n <
Ndof; n++)
1565 eigenfunction[0][n] =
Y[n];
1581 if (block_fold_solver_pt)
1586 delete block_fold_solver_pt;
1662 for (
unsigned n = 0; n <
Ndof; n++)
1708 std::cout <<
"Block pitchfork solve" << std::endl;
1720 if (!result.
built())
1723 OOMPH_CURRENT_FUNCTION,
1724 OOMPH_EXCEPTION_LOCATION);
1789 const unsigned n_dof_local =
F.nrow_local();
1792 for (
unsigned n = 0; n < n_dof_local; n++)
1799 unsigned offset = 1;
1800 #ifdef OOMPH_HAS_MPI
1805 if ((problem_pt->
distributed()) && (my_rank != 0))
1810 for (
unsigned n = 0; n < n_dof_local; n++)
1812 (*dJy_dparam_pt)[n] = dRdparam[n_dof_local + offset + n];
1824 double psi_d = psi.
dot(*
D_pt);
1825 double psi_c = psi.
dot(*
C_pt);
1826 double psi_x1 = psi.
dot(x1);
1829 const double Psi = psi_d / psi_c;
1838 double parameter_residual = result[n_dof_local];
1839 #ifdef OOMPH_HAS_MPI
1843 MPI_Bcast(¶meter_residual,
1851 double x2 = (psi_x1 - parameter_residual) / psi_c;
1859 const unsigned n_dof_local_linear_solver =
1861 for (
unsigned n = 0; n < n_dof_local_linear_solver; n++)
1863 const double C_ = (*C_pt)[n];
1864 D_and_X1[0][n] = (*D_pt)[n] - Psi * C_;
1865 D_and_X1[1][n] = x1[n] - x2 * C_;
1876 #ifdef OOMPH_HAS_MPI
1883 handler_pt->
Y, D_and_X1, Jprod_D_and_X1);
1891 for (
unsigned n = 0; n < n_dof_local; n++)
1893 G[n] = result[n_dof_local + offset + n] - Jprod_D_and_X1[1][n] -
1894 x2 * dRdparam[n_dof_local + offset + n];
1895 Jprod_D_and_X1[0][n] *= -1.0;
1896 Jprod_D_and_X1[0][n] -= Psi * dRdparam[n_dof_local + offset + n];
1912 double l_x3 = psi.
dot(x3);
1918 double sigma_residual = result[2 * (n_dof_local + offset) - 1];
1919 #ifdef OOMPH_HAS_MPI
1923 MPI_Bcast(&sigma_residual,
1932 const double delta_sigma = (l_x3 - sigma_residual) / l_b;
1933 const double delta_lambda = x2 - delta_sigma * Psi;
1942 for (
unsigned n = 0; n < n_dof_local_linear_solver; n++)
1944 res1[n] = x1[n] - delta_lambda * (*C_pt)[n] - delta_sigma * (*D_pt)[n];
1945 res2[n] = x3[n] - delta_sigma * (*B_pt)[n];
1953 for (
unsigned n = 0; n < n_dof_local; n++)
1955 result[n] = res1[n];
1956 result[n_dof_local + offset + n] = res2[n];
1961 #ifdef OOMPH_HAS_MPI
1962 if ((!problem_pt->
distributed()) || (my_rank == 0))
1965 result[n_dof_local] = delta_lambda;
1966 result[2 * n_dof_local + 1] = delta_sigma;
1974 static_cast<int>(std::fabs(psi_c * l_b) / (psi_c * l_b));
2010 std::cout <<
"Block pitchfork resolve" << std::endl;
2014 throw OomphLibError(
"The required vectors have not been stored",
2015 OOMPH_CURRENT_FUNCTION,
2016 OOMPH_EXCEPTION_LOCATION);
2040 if (!result.
built())
2042 result.
build(&aug_dist, 0.0);
2084 const unsigned n_dof_local = input_x1.
nrow_local();
2087 for (
unsigned n = 0; n < n_dof_local; n++)
2089 input_x1[n] = rhs_local[n];
2105 double psi_d = psi.
dot(*
D_pt);
2106 double psi_c = psi.
dot(*
C_pt);
2107 double psi_x1 = psi.
dot(x1);
2110 const double Psi = psi_d / psi_c;
2114 double parameter_residual = rhs_local[n_dof_local];
2115 #ifdef OOMPH_HAS_MPI
2119 MPI_Bcast(¶meter_residual,
2127 double x2 = (psi_x1 - parameter_residual) / psi_c;
2134 const unsigned n_dof_local_linear_solver =
2136 for (
unsigned n = 0; n < n_dof_local_linear_solver; n++)
2138 X1[0][n] = x1[n] - x2 * (*C_pt)[n];
2148 #ifdef OOMPH_HAS_MPI
2156 unsigned offset = 1;
2157 #ifdef OOMPH_HAS_MPI
2162 if ((problem_pt->
distributed()) && (my_rank != 0))
2173 for (
unsigned n = 0; n < n_dof_local; n++)
2175 Mod_Jprod_X1[n] = rhs_local[n_dof_local + offset + n] - Jprod_X1[0][n] -
2176 x2 * (*dJy_dparam_pt)[n];
2186 double l_x3 = psi.
dot(x3);
2192 double sigma_residual = rhs_local[2 * (n_dof_local + offset) - 1];
2193 #ifdef OOMPH_HAS_MPI
2197 MPI_Bcast(&sigma_residual,
2206 const double delta_sigma = (l_x3 - sigma_residual) / l_b;
2207 const double delta_lambda = x2 - delta_sigma * Psi;
2213 for (
unsigned n = 0; n < n_dof_local_linear_solver; n++)
2215 res1[n] = x1[n] - delta_lambda * (*C_pt)[n] - delta_sigma * (*D_pt)[n];
2216 res2[n] = x3[n] - delta_sigma * (*B_pt)[n];
2224 for (
unsigned n = 0; n < n_dof_local; n++)
2226 result[n] = res1[n];
2227 result[n_dof_local + offset + n] = res2[n];
2232 #ifdef OOMPH_HAS_MPI
2233 if ((!problem_pt->
distributed()) || (my_rank == 0))
2236 result[n_dof_local] = delta_lambda;
2237 result[2 * n_dof_local + 1] = delta_sigma;
2241 if (result_dist.
built())
2278 std::cout <<
"Augmented pitchfork solve" << std::endl;
2285 throw OomphLibError(
"The result vector must not be distributed",
2286 OOMPH_CURRENT_FUNCTION,
2287 OOMPH_EXCEPTION_LOCATION);
2301 unsigned n_dof = problem_pt->
ndof();
2309 if (!result.
built())
2332 for (
unsigned n = 0; n < (n_dof - 1); ++n)
2334 psi[n] = handler_pt->
Psi[n];
2337 psi[n_dof - 1] = 0.0;
2344 double dof_length = 0.0, a_length = 0.0, alpha_length = 0.0;
2345 for (
unsigned n = 0; n < n_dof; n++)
2347 if (std::fabs(problem_pt->
dof(n)) > dof_length)
2349 dof_length = std::fabs(problem_pt->
dof(n));
2351 if (std::fabs(a[n]) > a_length)
2353 a_length = std::fabs(a[n]);
2355 if (std::fabs((*
Alpha_pt)[n]) > alpha_length)
2357 alpha_length = std::fabs((*
Alpha_pt)[n]);
2361 double a_mult = dof_length / a_length;
2362 double alpha_mult = dof_length / alpha_length;
2363 const double FD_step = 1.0e-8;
2375 for (
unsigned long e = 0;
e < n_element;
e++)
2379 unsigned n_var = handler_pt->
ndof(elem_pt);
2390 for (
unsigned n = 0; n < n_var; n++)
2392 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
2393 dof_bac[n] = problem_pt->
dof(eqn_number);
2395 problem_pt->
dof(eqn_number) += a_mult * a[eqn_number];
2401 handler_pt->
get_jacobian(elem_pt, res_elemental, jac_a);
2404 for (
unsigned n = 0; n < n_var; n++)
2406 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
2407 problem_pt->
dof(eqn_number) = dof_bac[n];
2409 problem_pt->
dof(eqn_number) += alpha_mult * (*Alpha_pt)[eqn_number];
2415 handler_pt->
get_jacobian(elem_pt, res_elemental, jac_alpha);
2418 for (
unsigned n = 0; n < n_var; n++)
2420 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
2421 problem_pt->
dof(eqn_number) = dof_bac[n];
2427 for (
unsigned n = 0; n < (n_var - 1); n++)
2429 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
2430 double prod_a = 0.0, prod_alpha = 0.0;
2431 for (
unsigned m = 0; m < (n_var - 1); m++)
2433 unsigned unknown = handler_pt->
eqn_number(elem_pt, m);
2434 prod_a += (jac_a(n, m) - jac(n, m)) * handler_pt->
Y[unknown];
2435 prod_alpha += (jac_alpha(n, m) - jac(n, m)) * handler_pt->
Y[unknown];
2437 Jprod_a[eqn_number] += prod_a / a_mult;
2438 Jprod_alpha[eqn_number] += prod_alpha / alpha_mult;
2442 Jprod_alpha[n_dof - 1] = 0.0;
2443 Jprod_a[n_dof - 1] = 0.0;
2448 for (
unsigned n = 0; n < n_dof - 1; n++)
2450 b[n] = result[n_dof + n] - Jprod_a[n];
2452 b[n_dof - 1] = result[2 * n_dof - 1];
2468 const double e_final = (*E_pt)[n_dof - 1];
2470 const double d_final = -f[n_dof - 1] / e_final;
2472 for (
unsigned n = 0; n < n_dof - 1; n++)
2474 result[n] = a[n] - (*Alpha_pt)[n] * d_final;
2475 result[n_dof + n] = f[n] + (*E_pt)[n] * d_final;
2478 result[n_dof - 1] = a[n_dof - 1] - (*Alpha_pt)[n_dof - 1] * d_final;
2479 result[2 * n_dof - 1] = d_final;
2483 static_cast<int>(std::fabs(e_final) / e_final);
2513 std::cout <<
"Augmented pitchfork resolve" << std::endl;
2517 throw OomphLibError(
"The required vectors have not been stored",
2518 OOMPH_CURRENT_FUNCTION,
2519 OOMPH_EXCEPTION_LOCATION);
2531 unsigned n_dof = problem_pt->
ndof();
2539 if (!result.
built())
2550 for (
unsigned n = 0; n < n_dof; n++)
2566 double dof_length = 0.0, a_length = 0.0;
2567 for (
unsigned n = 0; n < n_dof; n++)
2569 if (std::fabs(problem_pt->
dof(n)) > dof_length)
2571 dof_length = std::fabs(problem_pt->
dof(n));
2574 if (std::fabs(a[n]) > a_length)
2576 a_length = std::fabs(a[n]);
2579 double a_mult = dof_length / a_length;
2580 const double FD_step = 1.0e-8;
2587 for (
unsigned long e = 0;
e < n_element;
e++)
2591 unsigned n_var = handler_pt->
ndof(elem_pt);
2602 for (
unsigned n = 0; n < n_var; n++)
2604 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
2605 dof_bac[n] = problem_pt->
dof(eqn_number);
2607 problem_pt->
dof(eqn_number) += a_mult * a[eqn_number];
2613 handler_pt->
get_jacobian(elem_pt, res_elemental, jac_a);
2616 for (
unsigned n = 0; n < n_var; n++)
2618 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
2619 problem_pt->
dof(eqn_number) = dof_bac[n];
2625 for (
unsigned n = 0; n < (n_var - 1); n++)
2627 unsigned eqn_number = handler_pt->
eqn_number(elem_pt, n);
2628 double prod_a = 0.0;
2629 for (
unsigned m = 0; m < (n_var - 1); m++)
2631 unsigned unknown = handler_pt->
eqn_number(elem_pt, m);
2632 prod_a += (jac_a(n, m) - jac(n, m)) * handler_pt->
Y[unknown];
2634 Jprod_a[eqn_number] += prod_a / a_mult;
2638 Jprod_a[n_dof - 1] = 0.0;
2641 for (
unsigned n = 0; n < n_dof - 1; n++)
2643 b[n] = rhs[n_dof + n] - Jprod_a[n];
2645 b[n_dof - 1] = rhs[2 * n_dof - 1];
2652 const double d_final = -f[n_dof - 1] / (*E_pt)[n_dof - 1];
2654 for (
unsigned n = 0; n < n_dof - 1; n++)
2656 result[n] = a[n] - (*Alpha_pt)[n] * d_final;
2657 result[n_dof + n] = f[n] + (*E_pt)[n] * d_final;
2660 result[n_dof - 1] = a[n_dof - 1] - (*Alpha_pt)[n_dof - 1] * d_final;
2661 result[2 * n_dof - 1] = d_final;
2680 double*
const& parameter_pt,
2682 : Solve_which_system(Full_augmented), Sigma(0.0), Parameter_pt(parameter_pt)
2692 #ifdef OOMPH_HAS_MPI
2700 #ifdef OOMPH_HAS_MPI
2714 #ifdef OOMPH_HAS_MPI
2720 unsigned n_non_halo_element_local = 0;
2721 for (
unsigned e = 0;
e < n_element;
e++)
2724 #ifdef OOMPH_HAS_MPI
2730 ++n_non_halo_element_local;
2732 unsigned n_var = assembly_handler_pt->
ndof(elem_pt);
2733 for (
unsigned n = 0; n < n_var; n++)
2737 #ifdef OOMPH_HAS_MPI
2743 #ifdef OOMPH_HAS_MPI
2750 MPI_Allreduce(&n_non_halo_element_local,
2761 Nelement = n_non_halo_element_local;
2764 #ifdef OOMPH_HAS_MPI
2775 double length = symmetry_vector.
norm();
2784 #ifdef OOMPH_HAS_MPI
2789 "The symmetry vector must have the same distribution as the dofs\n",
2790 OOMPH_CURRENT_FUNCTION,
2791 OOMPH_EXCEPTION_LOCATION);
2797 for (
unsigned n = 0; n < n_dof_local; n++)
2801 Psi[n] =
Y[n] =
C[n] = symmetry_vector[n] / length;
2805 #ifdef OOMPH_HAS_MPI
2820 #ifdef OOMPH_HAS_MPI
2823 unsigned augmented_first_row = 0;
2824 unsigned augmented_n_row_local = 0;
2829 unsigned global_eqn_count = 0;
2830 for (
int d = 0; d < n_proc; d++)
2835 augmented_first_row = global_eqn_count;
2841 for (
unsigned n = 0; n < n_row_local; n++)
2853 for (
unsigned n = 0; n < n_row_local; n++)
2867 augmented_n_row_local = global_eqn_count - augmented_first_row;
2874 augmented_first_row,
2875 augmented_n_row_local);
2904 if (block_pitchfork_solver_pt)
2910 delete block_pitchfork_solver_pt;
2920 if (augmented_block_pitchfork_solver_pt)
2926 delete augmented_block_pitchfork_solver_pt;
2946 unsigned raw_ndof = elem_pt->
ndof();
2952 return (2 * raw_ndof + 2);
2956 return (raw_ndof + 1);
2964 std::ostringstream error_stream;
2966 <<
"The Solve_which_system flag can only take values 0, 1, 2"
2969 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2975 const unsigned& ieqn_local)
2978 unsigned raw_ndof = elem_pt->
ndof();
2979 unsigned long global_eqn = 0;
2986 global_eqn = elem_pt->
eqn_number(ieqn_local);
2992 #ifdef OOMPH_HAS_MPI
2996 "Block Augmented solver not implemented for distributed case\n",
2997 OOMPH_CURRENT_FUNCTION,
2998 OOMPH_EXCEPTION_LOCATION);
3005 if (ieqn_local < raw_ndof)
3010 else if (ieqn_local == raw_ndof)
3016 else if (ieqn_local < (2 * raw_ndof + 1))
3038 unsigned raw_ndof = elem_pt->
ndof();
3049 for (
unsigned i = 0;
i < raw_ndof;
i++)
3066 residuals[raw_ndof] = 0.0;
3068 for (
unsigned i = 0;
i < raw_ndof;
i++)
3091 residuals[raw_ndof] = 0.0;
3092 residuals[2 * raw_ndof + 1] = -1.0 /
Nelement;
3096 for (
unsigned i = 0;
i < raw_ndof;
i++)
3099 residuals[raw_ndof + 1 +
i] = 0.0;
3100 for (
unsigned j = 0; j < raw_ndof; j++)
3102 unsigned local_unknown = elem_pt->
eqn_number(j);
3103 residuals[raw_ndof + 1 +
i] +=
3116 residuals[2 * raw_ndof + 1] +=
3124 std::ostringstream error_stream;
3126 <<
"The Solve_which_system flag can only take values 0, 1, 2"
3129 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3141 unsigned augmented_ndof =
ndof(elem_pt);
3142 unsigned raw_ndof = elem_pt->
ndof();
3154 for (
unsigned i = 0;
i < raw_ndof;
i++)
3175 const double FD_step = 1.0e-8;
3180 double init = *unknown_pt;
3191 for (
unsigned n = 0; n < raw_ndof; n++)
3193 jacobian(n, augmented_ndof - 1) =
3194 (newres[n] - residuals[n]) /
FD_step;
3204 for (
unsigned n = 0; n < raw_ndof; n++)
3207 jacobian(augmented_ndof - 1, n) =
3224 for (
unsigned n = 0; n < raw_ndof; n++)
3226 for (
unsigned m = 0; m < raw_ndof; m++)
3228 jacobian(raw_ndof + 1 + n, raw_ndof + 1 + m) = jacobian(n, m);
3232 jacobian(n, 2 * raw_ndof + 1) =
3235 jacobian(raw_ndof, n) =
3238 jacobian(2 * raw_ndof + 1, raw_ndof + 1 + n) =
3243 const double FD_step = 1.0e-8;
3248 for (
unsigned n = 0; n < raw_ndof; ++n)
3251 unsigned long global_eqn =
3254 double init = *unknown_pt;
3260 for (
unsigned m = 0; m < raw_ndof; m++)
3262 jacobian(raw_ndof + 1 + m, n) =
3263 (newres_p[raw_ndof + 1 + m] - residuals[raw_ndof + 1 + m]) /
3275 double init = *unknown_pt;
3283 for (
unsigned m = 0; m < raw_ndof; m++)
3285 jacobian(m, raw_ndof) = (newres_p[m] - residuals[m]) /
FD_step;
3288 for (
unsigned m = raw_ndof + 1; m < augmented_ndof - 1; m++)
3290 jacobian(m, raw_ndof) = (newres_p[m] - residuals[m]) /
FD_step;
3301 std::ostringstream error_stream;
3303 <<
"The Solve_which_system flag can only take values 0, 1, 2"
3306 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3318 double*
const& parameter_pt,
3322 unsigned raw_ndof = elem_pt->
ndof();
3344 dres_dparam[raw_ndof] = 0.0;
3357 parameter_pt, dres_dparam, djac_dparam);
3360 dres_dparam[raw_ndof] = 0.0;
3361 dres_dparam[2 * raw_ndof + 1] = 0.0;
3365 for (
unsigned i = 0;
i < raw_ndof;
i++)
3367 dres_dparam[raw_ndof + 1 +
i] = 0.0;
3368 for (
unsigned j = 0; j < raw_ndof; j++)
3370 unsigned local_unknown = elem_pt->
eqn_number(j);
3371 dres_dparam[raw_ndof + 1 +
i] +=
3379 std::ostringstream error_stream;
3381 <<
"The Solve_which_system flag can only take values 0, 1, 2"
3384 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3396 double*
const& parameter_pt,
3400 std::ostringstream error_stream;
3402 <<
"This function has not been implemented because it is not required\n";
3403 error_stream <<
"in standard problems.\n";
3405 <<
"If you find that you need it, you will have to implement it!\n\n";
3408 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
3433 eigenfunction.resize(1);
3437 const unsigned n_row_local = eigenfunction[0].nrow_local();
3438 for (
unsigned n = 0; n < n_row_local; n++)
3440 eigenfunction[0][n] =
Y[n];
3444 #ifdef OOMPH_HAS_MPI
3456 double broadcast_data[2];
3458 broadcast_data[1] =
Sigma;
3460 MPI_Bcast(broadcast_data,
3468 Sigma = broadcast_data[1];
3540 #ifdef OOMPH_HAS_MPI
3547 #ifdef OOMPH_HAS_MPI
3558 for (
unsigned n = 0; n < n_dof_local; n++)
3564 #ifdef OOMPH_HAS_MPI
3630 throw OomphLibError(
"The result vector must not be distributed",
3631 OOMPH_CURRENT_FUNCTION,
3632 OOMPH_EXCEPTION_LOCATION);
3642 unsigned n_dof = problem_pt->
ndof();
3653 const double FD_step = 1.0e-8;
3656 double* param_pt = &problem_pt->
dof(n_dof - 2);
3658 double old_var = *param_pt;
3668 for (
unsigned n = 0; n < n_dof; n++)
3670 dRdparam[n] = (dRdparam[n] - result[n]) /
FD_step;
3674 *param_pt = old_var;
3682 n_dof = problem_pt->
ndof();
3709 for (
unsigned n = 0; n < n_dof; n++)
3711 alpha[n] = dRdparam[n];
3740 double dof_length = 0.0, a_length = 0.0, y1_length = 0.0;
3742 for (
unsigned n = 0; n < n_dof; n++)
3744 if (std::fabs(problem_pt->
dof(n)) > dof_length)
3746 dof_length = std::fabs(problem_pt->
dof(n));
3748 if (std::fabs((*
A_pt)[n]) > a_length)
3750 a_length = std::fabs((*
A_pt)[n]);
3752 if (std::fabs(y1[n]) > y1_length)
3754 y1_length = std::fabs(y1[n]);
3758 double a_mult = dof_length / a_length;
3759 double y1_mult = dof_length / y1_length;
3766 Vector<double> Jprod_a(2 * n_dof, 0.0), Jprod_y1(2 * n_dof, 0.0);
3775 for (
unsigned long e = 0;
e < n_element;
e++)
3779 unsigned n_var = elem_pt->
ndof();
3789 for (
unsigned n = 0; n < n_var; n++)
3791 unsigned eqn_number = elem_pt->
eqn_number(n);
3792 dof_bac[n] = problem_pt->
dof(eqn_number);
3794 problem_pt->
dof(eqn_number) += a_mult * (*A_pt)[eqn_number];
3801 for (
unsigned n = 0; n < n_var; n++)
3803 unsigned eqn_number = elem_pt->
eqn_number(n);
3804 problem_pt->
dof(eqn_number) = dof_bac[n];
3806 problem_pt->
dof(eqn_number) += y1_mult * y1[eqn_number];
3813 for (
unsigned n = 0; n < n_var; n++)
3815 unsigned eqn_number = elem_pt->
eqn_number(n);
3816 problem_pt->
dof(eqn_number) = dof_bac[n];
3820 for (
unsigned n = 0; n < n_var; n++)
3822 unsigned eqn_number = elem_pt->
eqn_number(n);
3823 double prod_a1 = 0.0, prod_y11 = 0.0;
3824 double prod_a2 = 0.0, prod_y12 = 0.0;
3825 for (
unsigned m = 0; m < n_var; m++)
3827 const unsigned unknown = elem_pt->
eqn_number(m);
3828 const double y = handler_pt->
Phi[unknown];
3829 const double z = handler_pt->
Psi[unknown];
3830 const double omega = handler_pt->
Omega;
3833 (jac_a(n, m) - jac(n, m)) * y + omega * (M_a(n, m) - M(n, m)) * z;
3835 (jac_y1(n, m) - jac(n, m)) * y + omega * (M_y1(n, m) - M(n, m)) * z;
3838 (jac_a(n, m) - jac(n, m)) * z - omega * (M_a(n, m) - M(n, m)) * y;
3840 (jac_y1(n, m) - jac(n, m)) * z - omega * (M_y1(n, m) - M(n, m)) * y;
3842 Jprod_a[eqn_number] += prod_a1 / a_mult;
3843 Jprod_y1[eqn_number] += prod_y11 / y1_mult;
3844 Jprod_a[n_dof + eqn_number] += prod_a2 / a_mult;
3845 Jprod_y1[n_dof + eqn_number] += prod_y12 / y1_mult;
3851 for (
unsigned n = 0; n < 2 * n_dof; n++)
3853 rhs[n] = result[n_dof + n] - Jprod_y1[n];
3861 for (
unsigned i = 0;
i < 2 * n_dof;
i++)
3870 for (
unsigned n = 0; n < 2 * n_dof; n++)
3872 rhs[n] = dRdparam[n_dof + n] - Jprod_a[n];
3883 for (
unsigned i = 0;
i < 2 * n_dof;
i++)
3891 double dot_c = 0.0, dot_d = 0.0, dot_e = 0.0, dot_f = 0.0, dot_g = 0.0;
3894 for (
unsigned n = 0; n < n_dof; n++)
3897 const double Cn = handler_pt->
C[n];
3898 dot_c += Cn * y2[n];
3899 dot_d += Cn * y2[n_dof + n];
3900 dot_e += Cn * (*E_pt)[n];
3901 dot_f += Cn * (*E_pt)[n_dof + n];
3902 dot_g += Cn * (*G_pt)[n];
3903 dot_h += Cn * (*G_pt)[n_dof + n];
3907 double denom = dot_e * dot_h - dot_g * dot_f;
3910 double R31 = result[3 * n_dof], R32 = result[3 * n_dof + 1];
3912 const double delta_param =
3913 ((R32 - dot_d) * dot_g - (R31 - dot_c) * dot_h) / denom;
3915 const double delta_w = -((R32 - dot_d) + dot_f * delta_param) / (dot_h);
3918 result[3 * n_dof] = delta_param;
3919 result[3 * n_dof + 1] = delta_w;
3922 for (
unsigned n = 0; n < 2 * n_dof; n++)
3925 y2[n] - (*E_pt)[n] * delta_param - (*G_pt)[n] * delta_w;
3929 for (
unsigned n = 0; n < n_dof; n++)
3931 result[n] = y1[n] - (*A_pt)[n] * delta_param;
3937 sign_of_jacobian *
static_cast<int>(std::fabs(denom) / denom);
3977 throw OomphLibError(
"The result vector must not be distributed",
3978 OOMPH_CURRENT_FUNCTION,
3979 OOMPH_EXCEPTION_LOCATION);
3982 if (result2.
built())
3986 throw OomphLibError(
"The result2 vector must not be distributed",
3987 OOMPH_CURRENT_FUNCTION,
3988 OOMPH_EXCEPTION_LOCATION);
3998 unsigned n_dof = problem_pt->
ndof();
4006 if (!result.
built())
4010 if (!result2.
built())
4019 const double FD_step = 1.0e-8;
4022 double* param_pt = &problem_pt->
dof(n_dof - 2);
4024 double old_var = *param_pt;
4034 for (
unsigned n = 0; n < n_dof; n++)
4036 dRdparam[n] = (dRdparam[n] - result[n]) /
FD_step;
4040 *param_pt = old_var;
4048 n_dof = problem_pt->
ndof();
4076 for (
unsigned n = 0; n < n_dof; n++)
4078 alpha[n] = dRdparam[n];
4085 for (
unsigned n = 0; n < n_dof; n++)
4116 double dof_length = 0.0, a_length = 0.0, y1_length = 0.0,
4117 y1_resolve_length = 0.0;
4119 for (
unsigned n = 0; n < n_dof; n++)
4121 if (std::fabs(problem_pt->
dof(n)) > dof_length)
4123 dof_length = std::fabs(problem_pt->
dof(n));
4125 if (std::fabs((*
A_pt)[n]) > a_length)
4127 a_length = std::fabs((*
A_pt)[n]);
4129 if (std::fabs(y1[n]) > y1_length)
4131 y1_length = std::fabs(y1[n]);
4133 if (std::fabs(y1_resolve[n]) > y1_resolve_length)
4135 y1_resolve_length = std::fabs(y1[n]);
4140 double a_mult = dof_length / a_length;
4141 double y1_mult = dof_length / y1_length;
4142 double y1_resolve_mult = dof_length / y1_resolve_length;
4151 Vector<double> Jprod_a(2 * n_dof, 0.0), Jprod_y1(2 * n_dof, 0.0);
4161 for (
unsigned long e = 0;
e < n_element;
e++)
4165 unsigned n_var = elem_pt->
ndof();
4168 jac_y1_resolve(n_var);
4170 M_y1_resolve(n_var);
4177 for (
unsigned n = 0; n < n_var; n++)
4179 unsigned eqn_number = elem_pt->
eqn_number(n);
4180 dof_bac[n] = problem_pt->
dof(eqn_number);
4182 problem_pt->
dof(eqn_number) += a_mult * (*A_pt)[eqn_number];
4189 for (
unsigned n = 0; n < n_var; n++)
4191 unsigned eqn_number = elem_pt->
eqn_number(n);
4192 problem_pt->
dof(eqn_number) = dof_bac[n];
4194 problem_pt->
dof(eqn_number) += y1_mult * y1[eqn_number];
4201 for (
unsigned n = 0; n < n_var; n++)
4203 unsigned eqn_number = elem_pt->
eqn_number(n);
4204 problem_pt->
dof(eqn_number) = dof_bac[n];
4206 problem_pt->
dof(eqn_number) += y1_resolve_mult * y1_resolve[eqn_number];
4213 for (
unsigned n = 0; n < n_var; n++)
4215 unsigned eqn_number = elem_pt->
eqn_number(n);
4216 problem_pt->
dof(eqn_number) = dof_bac[n];
4220 for (
unsigned n = 0; n < n_var; n++)
4222 unsigned eqn_number = elem_pt->
eqn_number(n);
4223 double prod_a1 = 0.0, prod_y11 = 0.0, prod_y1_resolve1 = 0.0;
4224 double prod_a2 = 0.0, prod_y12 = 0.0, prod_y1_resolve2 = 0.0;
4225 for (
unsigned m = 0; m < n_var; m++)
4227 const unsigned unknown = elem_pt->
eqn_number(m);
4228 const double y = handler_pt->
Phi[unknown];
4229 const double z = handler_pt->
Psi[unknown];
4230 const double omega = handler_pt->
Omega;
4233 (jac_a(n, m) - jac(n, m)) * y + omega * (M_a(n, m) - M(n, m)) * z;
4235 (jac_y1(n, m) - jac(n, m)) * y + omega * (M_y1(n, m) - M(n, m)) * z;
4236 prod_y1_resolve1 += (jac_y1_resolve(n, m) - jac(n, m)) * y +
4237 omega * (M_y1_resolve(n, m) - M(n, m)) * z;
4240 (jac_a(n, m) - jac(n, m)) * z - omega * (M_a(n, m) - M(n, m)) * y;
4242 (jac_y1(n, m) - jac(n, m)) * z - omega * (M_y1(n, m) - M(n, m)) * y;
4243 prod_y1_resolve2 += (jac_y1_resolve(n, m) - jac(n, m)) * z -
4244 omega * (M_y1_resolve(n, m) - M(n, m)) * y;
4246 Jprod_a[eqn_number] += prod_a1 / a_mult;
4247 Jprod_y1[eqn_number] += prod_y11 / y1_mult;
4248 Jprod_y1_resolve[eqn_number] += prod_y1_resolve1 / y1_resolve_mult;
4249 Jprod_a[n_dof + eqn_number] += prod_a2 / a_mult;
4250 Jprod_y1[n_dof + eqn_number] += prod_y12 / y1_mult;
4251 Jprod_y1_resolve[n_dof + eqn_number] +=
4252 prod_y1_resolve2 / y1_resolve_mult;
4258 for (
unsigned n = 0; n < 2 * n_dof; n++)
4260 rhs[n] = result[n_dof + n] - Jprod_y1[n];
4268 for (
unsigned i = 0;
i < 2 * n_dof;
i++)
4270 temp_rhs[
i] = rhs[
i];
4275 for (
unsigned n = 0; n < 2 * n_dof; n++)
4277 rhs[n] = dRdparam[n_dof + n] - Jprod_a[n];
4288 for (
unsigned i = 0;
i < 2 * n_dof;
i++)
4290 temp_rhs[
i] = rhs[
i];
4295 for (
unsigned n = 0; n < 2 * n_dof; n++)
4297 rhs[n] = rhs2[n_dof + n] - Jprod_y1_resolve[n];
4301 for (
unsigned i = 0;
i < 2 * n_dof;
i++)
4303 temp_rhs[
i] = rhs[
i];
4310 double dot_c = 0.0, dot_d = 0.0, dot_e = 0.0, dot_f = 0.0, dot_g = 0.0;
4313 double dot_c_resolve = 0.0, dot_d_resolve = 0.0;
4315 for (
unsigned n = 0; n < n_dof; n++)
4318 const double Cn = handler_pt->
C[n];
4319 dot_c += Cn * y2[n];
4320 dot_d += Cn * y2[n_dof + n];
4321 dot_c_resolve += Cn * y2_resolve[n];
4322 dot_d_resolve += Cn * y2_resolve[n_dof + n];
4323 dot_e += Cn * (*E_pt)[n];
4324 dot_f += Cn * (*E_pt)[n_dof + n];
4325 dot_g += Cn * (*G_pt)[n];
4326 dot_h += Cn * (*G_pt)[n_dof + n];
4330 double denom = dot_e * dot_h - dot_g * dot_f;
4333 double R31 = result[3 * n_dof], R32 = result[3 * n_dof + 1];
4335 const double delta_param =
4336 ((R32 - dot_d) * dot_g - (R31 - dot_c) * dot_h) / denom;
4338 const double delta_w = -((R32 - dot_d) + dot_f * delta_param) / (dot_h);
4341 double R31_resolve = rhs2[3 * n_dof], R32_resolve = rhs2[3 * n_dof + 1];
4343 const double delta_param_resolve = ((R32_resolve - dot_d_resolve) * dot_g -
4344 (R31_resolve - dot_c_resolve) * dot_h) /
4347 const double delta_w_resolve =
4348 -((R32_resolve - dot_d_resolve) + dot_f * delta_param_resolve) / (dot_h);
4352 result[3 * n_dof] = delta_param;
4353 result[3 * n_dof + 1] = delta_w;
4356 for (
unsigned n = 0; n < 2 * n_dof; n++)
4359 y2[n] - (*E_pt)[n] * delta_param - (*G_pt)[n] * delta_w;
4363 for (
unsigned n = 0; n < n_dof; n++)
4365 result[n] = y1[n] - (*A_pt)[n] * delta_param;
4369 result2[3 * n_dof] = delta_param_resolve;
4370 result2[3 * n_dof + 1] = delta_w_resolve;
4373 for (
unsigned n = 0; n < 2 * n_dof; n++)
4375 result2[n_dof + n] = y2_resolve[n] - (*E_pt)[n] * delta_param_resolve -
4376 (*G_pt)[n] * delta_w_resolve;
4380 for (
unsigned n = 0; n < n_dof; n++)
4382 result2[n] = y1_resolve[n] - (*A_pt)[n] * delta_param_resolve;
4389 sign_of_jacobian *
static_cast<int>(std::fabs(denom) / denom);
4420 throw OomphLibError(
"resolve() is not implemented for this solver",
4421 OOMPH_CURRENT_FUNCTION,
4422 OOMPH_EXCEPTION_LOCATION);
4436 double*
const& parameter_pt)
4437 : Solve_which_system(0), Parameter_pt(parameter_pt), Omega(0.0)
4457 for (
unsigned e = 0;
e < n_element;
e++)
4461 unsigned n_var = elem_pt->
ndof();
4462 for (
unsigned n = 0; n < n_var; n++)
4487 linear_solver_pt->
solve(problem_pt, x);
4498 linear_solver_pt->
resolve(input_x, x);
4511 double length = 0.0;
4512 for (
unsigned n = 0; n <
Ndof; n++)
4514 length += x[n] * x[n];
4516 length = sqrt(length);
4521 for (
unsigned n = 0; n <
Ndof; n++)
4524 C[n] =
Phi[n] = -x[n] / length;
4529 for (
unsigned n = 0; n <
Ndof; n += 2)
4545 for (
unsigned n = 0; n <
Ndof; n++)
4550 problem_pt->
Dof_pt.push_back(parameter_pt);
4570 double*
const& parameter_pt,
4571 const double& omega,
4574 : Solve_which_system(0), Parameter_pt(parameter_pt), Omega(omega)
4589 for (
unsigned e = 0;
e < n_element;
e++)
4593 unsigned n_var = elem_pt->
ndof();
4594 for (
unsigned n = 0; n < n_var; n++)
4602 double length = 0.0;
4603 for (
unsigned n = 0; n <
Ndof; n++)
4605 length += phi[n] * phi[n];
4607 length = sqrt(length);
4611 for (
unsigned n = 0; n <
Ndof; n++)
4614 C[n] =
Phi[n] = phi[n] / length;
4615 Psi[n] = psi[n] / length;
4619 for (
unsigned n = 0; n <
Ndof; n++)
4625 problem_pt->
Dof_pt.push_back(parameter_pt);
4646 if (block_hopf_solver_pt)
4651 delete block_hopf_solver_pt;
4667 unsigned raw_ndof = elem_pt->
ndof();
4672 return (3 * raw_ndof + 2);
4680 return (2 * raw_ndof);
4684 throw OomphLibError(
"Solve_which_system can only be 0,1 or 2",
4685 OOMPH_CURRENT_FUNCTION,
4686 OOMPH_EXCEPTION_LOCATION);
4694 const unsigned& ieqn_local)
4697 unsigned raw_ndof = elem_pt->
ndof();
4698 unsigned long global_eqn;
4699 if (ieqn_local < raw_ndof)
4701 global_eqn = elem_pt->
eqn_number(ieqn_local);
4703 else if (ieqn_local < 2 * raw_ndof)
4707 else if (ieqn_local < 3 * raw_ndof)
4709 global_eqn = 2 *
Ndof + elem_pt->
eqn_number(ieqn_local - 2 * raw_ndof);
4711 else if (ieqn_local == 3 * raw_ndof)
4713 global_eqn = 3 *
Ndof;
4717 global_eqn = 3 *
Ndof + 1;
4732 unsigned raw_ndof = elem_pt->
ndof();
4739 residuals[3 * raw_ndof] =
4741 residuals[3 * raw_ndof + 1] = 0.0;
4744 for (
unsigned i = 0;
i < raw_ndof;
i++)
4746 residuals[raw_ndof +
i] = 0.0;
4747 residuals[2 * raw_ndof +
i] = 0.0;
4748 for (
unsigned j = 0; j < raw_ndof; j++)
4750 unsigned global_unknown = elem_pt->
eqn_number(j);
4752 residuals[raw_ndof +
i] += jacobian(
i, j) *
Phi[global_unknown] +
4755 residuals[2 * raw_ndof +
i] += jacobian(
i, j) *
Psi[global_unknown] -
4762 residuals[3 * raw_ndof] +=
4763 (
Phi[global_eqn] *
C[global_eqn]) /
Count[global_eqn];
4765 residuals[3 * raw_ndof + 1] +=
4766 (
Psi[global_eqn] *
C[global_eqn]) /
Count[global_eqn];
4772 OOMPH_CURRENT_FUNCTION,
4773 OOMPH_EXCEPTION_LOCATION);
4789 unsigned augmented_ndof =
ndof(elem_pt);
4790 unsigned raw_ndof = elem_pt->
ndof();
4799 for (
unsigned n = 0; n < raw_ndof; ++n)
4801 for (
unsigned m = 0; m < raw_ndof; ++m)
4803 jacobian(raw_ndof + n, raw_ndof + m) = jacobian(n, m);
4804 jacobian(raw_ndof + n, 2 * raw_ndof + m) =
Omega * M(n, m);
4805 jacobian(2 * raw_ndof + n, 2 * raw_ndof + m) = jacobian(n, m);
4806 jacobian(2 * raw_ndof + n, raw_ndof + m) = -
Omega * M(n, m);
4807 unsigned global_eqn = elem_pt->
eqn_number(m);
4808 jacobian(raw_ndof + n, 3 * raw_ndof + 1) += M(n, m) *
Psi[global_eqn];
4809 jacobian(2 * raw_ndof + n, 3 * raw_ndof + 1) -=
4810 M(n, m) *
Phi[global_eqn];
4814 jacobian(3 * raw_ndof, raw_ndof + n) =
C[local_eqn] /
Count[local_eqn];
4815 jacobian(3 * raw_ndof + 1, 2 * raw_ndof + n) =
4816 C[local_eqn] /
Count[local_eqn];
4819 const double FD_step = 1.0e-8;
4821 Vector<double> newres_p(augmented_ndof), newres_m(augmented_ndof);
4824 for (
unsigned n = 0; n < raw_ndof; n++)
4827 unsigned long global_eqn =
eqn_number(elem_pt, n);
4829 double init = *unknown_pt;
4842 for (
unsigned m = 0; m < raw_ndof; m++)
4844 jacobian(raw_ndof + m, n) =
4845 (newres_p[raw_ndof + m] - residuals[raw_ndof + m]) / (
FD_step);
4846 jacobian(2 * raw_ndof + m, n) =
4847 (newres_p[2 * raw_ndof + m] - residuals[2 * raw_ndof + m]) /
4857 double init = *unknown_pt;
4871 for (
unsigned m = 0; m < augmented_ndof - 2; m++)
4873 jacobian(m, 3 * raw_ndof) = (newres_p[m] - residuals[m]) /
FD_step;
4889 unsigned raw_ndof = elem_pt->
ndof();
4896 for (
unsigned n = 0; n < raw_ndof; n++)
4898 for (
unsigned m = 0; m < raw_ndof; m++)
4900 jacobian(n, raw_ndof + m) =
Omega * M(n, m);
4901 jacobian(raw_ndof + n, m) = -
Omega * M(n, m);
4902 jacobian(raw_ndof + n, raw_ndof + m) = jacobian(n, m);
4910 for (
unsigned n = 0; n < raw_ndof; n++)
4913 residuals[raw_ndof + n] = 0.0;
4914 for (
unsigned m = 0; m < raw_ndof; m++)
4916 unsigned global_unknown = elem_pt->
eqn_number(m);
4918 residuals[n] += M(n, m) *
Psi[global_unknown];
4920 residuals[raw_ndof + n] -= M(n, m) *
Phi[global_unknown];
4926 throw OomphLibError(
"Solve_which_system can only be 0,1 or 2",
4927 OOMPH_CURRENT_FUNCTION,
4928 OOMPH_EXCEPTION_LOCATION);
4939 double*
const& parameter_pt,
4946 unsigned raw_ndof = elem_pt->
ndof();
4951 parameter_pt, dres_dparam, djac_dparam, dM_dparam);
4955 dres_dparam[3 * raw_ndof] = 0.0;
4956 dres_dparam[3 * raw_ndof + 1] = 0.0;
4959 for (
unsigned i = 0;
i < raw_ndof;
i++)
4961 dres_dparam[raw_ndof +
i] = 0.0;
4962 dres_dparam[2 * raw_ndof +
i] = 0.0;
4963 for (
unsigned j = 0; j < raw_ndof; j++)
4965 unsigned global_unknown = elem_pt->
eqn_number(j);
4967 dres_dparam[raw_ndof +
i] +=
4968 djac_dparam(
i, j) *
Phi[global_unknown] +
4969 Omega * dM_dparam(
i, j) *
Psi[global_unknown];
4971 dres_dparam[2 * raw_ndof +
i] +=
4972 djac_dparam(
i, j) *
Psi[global_unknown] -
4973 Omega * dM_dparam(
i, j) *
Phi[global_unknown];
4980 OOMPH_CURRENT_FUNCTION,
4981 OOMPH_EXCEPTION_LOCATION);
4992 double*
const& parameter_pt,
4996 std::ostringstream error_stream;
4998 <<
"This function has not been implemented because it is not required\n";
4999 error_stream <<
"in standard problems.\n";
5001 <<
"If you find that you need it, you will have to implement it!\n\n";
5004 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
5018 std::ostringstream error_stream;
5020 <<
"This function has not been implemented because it is not required\n";
5021 error_stream <<
"in standard problems.\n";
5023 <<
"If you find that you need it, you will have to implement it!\n\n";
5026 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
5037 eigenfunction.resize(2);
5040 eigenfunction[0].build(&dist, 0.0);
5041 eigenfunction[1].build(&dist, 0.0);
5043 for (
unsigned n = 0; n <
Ndof; n++)
5045 eigenfunction[0][n] =
Phi[n];
5046 eigenfunction[1][n] =
Psi[n];
5082 for (
unsigned n = 0; n <
Ndof; n++)
5108 for (
unsigned n = 0; n <
Ndof; n++)
5112 for (
unsigned n = 0; n <
Ndof; n++)
A class that is used to define the functions used to assemble the elemental contributions to the resi...
virtual unsigned ndof(GeneralisedElement *const &elem_pt)
Return the number of degrees of freedom in the element elem_pt.
virtual void get_hessian_vector_products(GeneralisedElement *const &elem_pt, Vector< double > const &Y, DenseMatrix< double > const &C, DenseMatrix< double > &product)
Calculate the product of the Hessian (derivative of Jacobian with respect to all variables) an eigenv...
virtual void get_dresiduals_dparameter(GeneralisedElement *const &elem_pt, double *const ¶meter_pt, Vector< double > &dres_dparam)
Calculate the derivative of the residuals with respect to a parameter.
virtual double * bifurcation_parameter_pt() const
Return a pointer to the bifurcation parameter in bifurcation tracking problems.
virtual void get_all_vectors_and_matrices(GeneralisedElement *const &elem_pt, Vector< Vector< double >> &vec, Vector< DenseMatrix< double >> &matrix)
Calculate all desired vectors and matrices provided by the element elem_pt.
virtual void get_eigenfunction(Vector< DoubleVector > &eigenfunction)
Return the eigenfunction(s) associated with the bifurcation that has been detected in bifurcation tra...
virtual void get_residuals(GeneralisedElement *const &elem_pt, Vector< double > &residuals)
Return the contribution to the residuals of the element elem_pt.
virtual unsigned long eqn_number(GeneralisedElement *const &elem_pt, const unsigned &ieqn_local)
Return the global equation number of the local unknown ieqn_local in elem_pt.
virtual double & local_problem_dof(Problem *const &problem_pt, const unsigned &t, const unsigned &i)
Return the t-th level of storage associated with the i-th (local) dof stored in the problem.
virtual void get_inner_products(GeneralisedElement *const &elem_pt, Vector< std::pair< unsigned, unsigned >> const &history_index, Vector< double > &inner_product)
Compute the inner products of the given vector of pairs of history values over the element.
virtual void dof_vector(GeneralisedElement *const &elem_pt, const unsigned &t, Vector< double > &dof)
Return vector of dofs at time level t in the element elem_pt.
virtual void get_jacobian(GeneralisedElement *const &elem_pt, Vector< double > &residuals, DenseMatrix< double > &jacobian)
Calculate the elemental Jacobian matrix "d equation / d variable" for elem_pt.
virtual void get_djacobian_dparameter(GeneralisedElement *const &elem_pt, double *const ¶meter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam)
Calculate the derivative of the residuals and jacobian with respect to a parameter.
virtual void get_inner_product_vectors(GeneralisedElement *const &elem_pt, Vector< unsigned > const &history_index, Vector< Vector< double >> &inner_product_vector)
Compute the vectors that when taken as a dot product with other history values give the inner product...
virtual void dof_pt_vector(GeneralisedElement *const &elem_pt, Vector< double * > &dof_pt)
Return vector of pointers to dofs in the element elem_pt.
A custom linear solver class that is used to solve a block-factorised version of the Fold bifurcation...
void solve(Problem *const &problem_pt, DoubleVector &result)
The solve function uses the block factorisation.
LinearSolver * Linear_solver_pt
Pointer to the original linear solver.
LinearSolver * linear_solver_pt() const
Access function to the original linear solver.
DoubleVector * E_pt
Pointer to the storage for the vector e.
void resolve(const DoubleVector &rhs, DoubleVector &result)
The resolve function also uses the block factorisation.
~AugmentedBlockFoldLinearSolver()
Destructor: clean up the allocated memory.
DoubleVector * Alpha_pt
Pointer to the storage for the vector alpha.
A custom linear solver class that is used to solve a block-factorised version of the PitchFork bifurc...
void solve(Problem *const &problem_pt, DoubleVector &result)
The solve function uses the block factorisation.
LinearSolver * Linear_solver_pt
Pointer to the original linear solver.
void resolve(const DoubleVector &rhs, DoubleVector &result)
The resolve function also uses the block factorisation.
DoubleVector * Alpha_pt
Pointer to the storage for the vector alpha.
DoubleVector * E_pt
Pointer to the storage for the vector e.
LinearSolver * linear_solver_pt() const
Access function to the original linear solver.
~AugmentedBlockPitchForkLinearSolver()
Destructor: clean up the allocated memory.
Problem * Problem_pt
Pointer to the problem, used in the resolve.
A custom linear solver class that is used to solve a block-factorised version of the Hopf bifurcation...
LinearSolver * Linear_solver_pt
Pointer to the original linear solver.
void resolve(const DoubleVector &rhs, DoubleVector &result)
The resolve function also uses the block factorisation.
DoubleVector * A_pt
Pointer to the storage for the vector a.
void solve(Problem *const &problem_pt, DoubleVector &result)
The solve function uses the block factorisation.
Problem * Problem_pt
Pointer to the problem, used in the resolve.
~BlockHopfLinearSolver()
Destructor: clean up the allocated memory.
void solve_for_two_rhs(Problem *const &problem_pt, DoubleVector &result, const DoubleVector &rhs2, DoubleVector &result2)
Solve for two right hand sides.
DoubleVector * E_pt
Pointer to the storage for the vector e (0 to n-1)
DoubleVector * G_pt
Pointer to the storage for the vector g (0 to n-1)
LinearSolver * linear_solver_pt() const
Access function to the original linear solver.
A custom linear solver class that is used to solve a block-factorised version of the PitchFork bifurc...
DoubleVector * D_pt
Pointer to the storage for the vector d.
LinearSolver * linear_solver_pt() const
Access function to the original linear solver.
DoubleVector * dJy_dparam_pt
Pointer to the storage for the vector of derivatives with respect to the bifurcation parameter.
~BlockPitchForkLinearSolver()
Destructor: clean up the allocated memory.
DoubleVector * B_pt
Pointer to the storage for the vector b.
Problem * Problem_pt
Pointer to the problem, used in the resolve.
void resolve(const DoubleVector &rhs, DoubleVector &result)
The resolve function also uses the block factorisation.
DoubleVector * C_pt
Pointer to the storage for the vector c.
void solve(Problem *const &problem_pt, DoubleVector &result)
The solve function uses the block factorisation.
LinearSolver * Linear_solver_pt
Pointer to the original linear solver.
bool distributed() const
distribution is serial or distributed
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
unsigned nrow_local() const
access function for the num of local rows on this processor.
void build_distribution(const LinearAlgebraDistribution *const dist_pt)
setup the distribution of this distributable linear algebra object
void build_halo_scheme(DoubleVectorHaloScheme *const &halo_scheme_pt)
Construct the halo scheme and storage for the halo data.
void synchronise()
Synchronise the halo data.
void sum_all_halo_and_haloed_values()
Sum all the data, store in the master (haloed) data and then synchronise.
double & global_value(const unsigned &i)
Direct access to global entry.
A vector in the mathematical sense, initially developed for linear algebra type applications....
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
void redistribute(const LinearAlgebraDistribution *const &dist_pt)
The contents of the vector are redistributed to match the new distribution. In a non-MPI rebuild this...
double norm() const
compute the 2 norm of this vector
double dot(const DoubleVector &vec) const
compute the dot product of this vector with the vector vec.
void get_residuals(GeneralisedElement *const &elem_pt, Vector< double > &residuals)
Return the contribution to the residuals of the element elem_pt This is deliberately broken in our ei...
double Sigma_real
Storage for the real shift.
void get_all_vectors_and_matrices(GeneralisedElement *const &elem_pt, Vector< Vector< double >> &vec, Vector< DenseMatrix< double >> &matrix)
Calculate all desired vectors and matrices provided by the element elem_pt.
void get_jacobian(GeneralisedElement *const &elem_pt, Vector< double > &residuals, DenseMatrix< double > &jacobian)
Calculate the elemental Jacobian matrix "d equation / d variable" for elem_pt. Again deliberately bro...
unsigned long eqn_number(GeneralisedElement *const &elem_pt, const unsigned &ieqn_local)
Return the global equation number of the local unknown ieqn_local in elem_pt.
unsigned ndof(GeneralisedElement *const &elem_pt)
Return the number of degrees of freedom in the element elem_pt.
unsigned long eqn_number(GeneralisedElement *const &elem_pt, const unsigned &ieqn_local)
Return the global equation number of the local unknown ieqn_local in elem_pt.
unsigned ndof(GeneralisedElement *const &elem_pt)
Return the number of degrees of freedom in the element elem_pt.
void get_all_vectors_and_matrices(GeneralisedElement *const &elem_pt, Vector< Vector< double >> &vec, Vector< DenseMatrix< double >> &matrix)
Calculate all desired vectors and matrices provided by the element elem_pt.
void get_jacobian(GeneralisedElement *const &elem_pt, Vector< double > &residuals, DenseMatrix< double > &jacobian)
Calculate the elemental Jacobian matrix "d equation / d variable" for elem_pt. Again deliberately bro...
void get_residuals(GeneralisedElement *const &elem_pt, Vector< double > &residuals)
Return the contribution to the residuals of the element elem_pt This is deliberately broken in our ei...
A class that is used to assemble the augmented system that defines a fold (saddle-node) or limit poin...
Problem * Problem_pt
Pointer to the problem.
Vector< int > Count
A vector that is used to determine how many elements contribute to a particular equation....
unsigned long eqn_number(GeneralisedElement *const &elem_pt, const unsigned &ieqn_local)
Get the global equation number of the local unknown.
void solve_full_system()
Solve non-block system.
void get_djacobian_dparameter(GeneralisedElement *const &elem_pt, double *const ¶meter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam)
Overload the derivative of the residuals and jacobian with respect to a parameter so that it breaks.
unsigned Solve_which_system
Integer flag to indicate which system should be assembled. There are three possibilities....
void solve_augmented_block_system()
Set to solve the augmented block system.
Vector< double > Phi
A constant vector used to ensure that the null vector is not trivial.
unsigned Ndof
Store the number of degrees of freedom in the non-augmented problem.
void get_hessian_vector_products(GeneralisedElement *const &elem_pt, Vector< double > const &Y, DenseMatrix< double > const &C, DenseMatrix< double > &product)
Overload the hessian vector product function so that it breaks.
~FoldHandler()
Destructor, return the problem to its original state before the augmented system was added.
void solve_block_system()
Set to solve the block system.
void get_residuals(GeneralisedElement *const &elem_pt, Vector< double > &residuals)
Get the residuals.
Vector< double > Y
Storage for the null vector.
void get_eigenfunction(Vector< DoubleVector > &eigenfunction)
Return the eigenfunction(s) associated with the bifurcation that has been detected in bifurcation tra...
void get_jacobian(GeneralisedElement *const &elem_pt, Vector< double > &residuals, DenseMatrix< double > &jacobian)
Calculate the elemental Jacobian matrix "d equation / d variable".
void get_dresiduals_dparameter(GeneralisedElement *const &elem_pt, double *const ¶meter_pt, Vector< double > &dres_dparam)
Overload the derivatives of the residuals with respect to a parameter to apply to the augmented syste...
FoldHandler(Problem *const &problem_pt, double *const ¶meter_pt)
Constructor: initialise the fold handler, by setting initial guesses for Y, Phi and calculating count...
double * Parameter_pt
Storage for the pointer to the parameter.
unsigned ndof(GeneralisedElement *const &elem_pt)
Get the number of elemental degrees of freedom.
A Generalised Element class.
bool is_halo() const
Is this element a halo?
void dof_vector(const unsigned &t, Vector< double > &dof)
Return the vector of dof values at time level t.
virtual void get_inner_products(Vector< std::pair< unsigned, unsigned >> const &history_index, Vector< double > &inner_product)
Return the vector of inner product of the given pairs of history values.
virtual void get_hessian_vector_products(Vector< double > const &Y, DenseMatrix< double > const &C, DenseMatrix< double > &product)
Calculate the product of the Hessian (derivative of Jacobian with respect to all variables) an eigenv...
unsigned ndof() const
Return the number of equations/dofs in the element.
unsigned long eqn_number(const unsigned &ieqn_local) const
Return the global equation number corresponding to the ieqn_local-th local equation number.
virtual void get_residuals(Vector< double > &residuals)
Calculate the vector of residuals of the equations in the element. By default initialise the vector t...
virtual void get_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &mass_matrix)
Calculate the residuals and the elemental "mass" matrix, the matrix that multiplies the time derivati...
virtual void get_dresiduals_dparameter(double *const ¶meter_pt, Vector< double > &dres_dparam)
Calculate the derivatives of the residuals with respect to a parameter.
void dof_pt_vector(Vector< double * > &dof_pt)
Return the vector of pointers to dof values.
virtual void get_inner_product_vectors(Vector< unsigned > const &history_index, Vector< Vector< double >> &inner_product_vector)
Compute the vectors that when taken as a dot product with other history values give the inner product...
virtual void get_djacobian_and_dmass_matrix_dparameter(double *const ¶meter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam, DenseMatrix< double > &dmass_matrix_dparam)
Calculate the derivatives of the elemental Jacobian matrix mass matrix and residuals with respect to ...
virtual void get_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Calculate the elemental Jacobian matrix "d equation / d variable".
virtual void get_djacobian_dparameter(double *const ¶meter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam)
Calculate the derivatives of the elemental Jacobian matrix and residuals with respect to a parameter.
virtual void get_jacobian_and_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix)
Calculate the residuals and jacobian and elemental "mass" matrix, the matrix that multiplies the time...
A class that is used to assemble the augmented system that defines a Hopf bifurcation....
Vector< double > Phi
The real part of the null vector.
Vector< int > Count
A vector that is used to determine how many elements contribute to a particular equation....
double Omega
The critical frequency of the bifurcation.
void get_dresiduals_dparameter(GeneralisedElement *const &elem_pt, double *const ¶meter_pt, Vector< double > &dres_dparam)
Overload the derivatives of the residuals with respect to a parameter to apply to the augmented syste...
~HopfHandler()
Destructor, return the problem to its original state, before the augmented system was added.
void solve_full_system()
Solve non-block system.
void get_djacobian_dparameter(GeneralisedElement *const &elem_pt, double *const ¶meter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam)
Overload the derivative of the residuals and jacobian with respect to a parameter so that it breaks.
void get_residuals(GeneralisedElement *const &elem_pt, Vector< double > &residuals)
Get the residuals.
void get_hessian_vector_products(GeneralisedElement *const &elem_pt, Vector< double > const &Y, DenseMatrix< double > const &C, DenseMatrix< double > &product)
Overload the hessian vector product function so that it breaks.
unsigned ndof(GeneralisedElement *const &elem_pt)
Get the number of elemental degrees of freedom.
Vector< double > C
A constant vector used to ensure that the null vector is not trivial.
void get_eigenfunction(Vector< DoubleVector > &eigenfunction)
Return the eigenfunction(s) associated with the bifurcation that has been detected in bifurcation tra...
Vector< double > Psi
The imaginary part of the null vector.
unsigned long eqn_number(GeneralisedElement *const &elem_pt, const unsigned &ieqn_local)
Get the global equation number of the local unknown.
unsigned Solve_which_system
Integer flag to indicate which system should be assembled. There are three possibilities....
Problem * Problem_pt
Pointer to the problem.
void get_jacobian(GeneralisedElement *const &elem_pt, Vector< double > &residuals, DenseMatrix< double > &jacobian)
Calculate the elemental Jacobian matrix "d equation / d variable".
HopfHandler(Problem *const &problem_pt, double *const ¶meter_pt)
Constructor.
unsigned Ndof
Store the number of degrees of freedom in the non-augmented problem.
void solve_complex_system()
Set to solve the complex system.
void solve_standard_system()
Set to solve the standard system.
double * Parameter_pt
Pointer to the parameter.
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
unsigned first_row() const
access function for the first row on this processor. If not distributed then this is just zero.
void build(const OomphCommunicator *const comm_pt, const unsigned &first_row, const unsigned &nrow_local, const unsigned &nrow=0)
Sets the distribution. Takes first_row, nrow_local and nrow as arguments. If nrow is not provided or ...
bool built() const
if the communicator_pt is null then the distribution is not setup then false is returned,...
unsigned nrow_local() const
access function for the num of local rows on this processor. If no MPI then Nrow is returned.
Base class for all linear solvers. This merely defines standard interfaces for linear solvers,...
virtual void solve(Problem *const &problem_pt, DoubleVector &result)=0
Solver: Takes pointer to problem and returns the results vector which contains the solution of the li...
virtual void enable_resolve()
Enable resolve (i.e. store matrix and/or LU decomposition, say) Virtual so it can be overloaded to pe...
virtual void resolve(const DoubleVector &rhs, DoubleVector &result)
Resolve the system defined by the last assembled jacobian and the rhs vector. Solution is returned in...
bool Enable_resolve
Boolean that indicates whether the matrix (or its factors, in the case of direct solver) should be st...
virtual void disable_resolve()
Disable resolve (i.e. store matrix and/or LU decomposition, say) This function simply resets an inter...
bool is_resolve_enabled() const
Boolean flag indicating if resolves are enabled.
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
unsigned long nelement() const
Return number of elements in the mesh.
An OomphLibError object which should be thrown when an run-time error is encountered....
A class that is used to assemble the augmented system that defines a pitchfork (symmetry-breaking) bi...
LinearAlgebraDistribution * Dof_distribution_pt
Store the original dof distribution.
Problem * Problem_pt
Pointer to the problem.
void synchronise()
Function that is used to perform any synchronisation required during the solution.
void solve_full_system()
Solve non-block system.
DoubleVectorWithHaloEntries Y
Storage for the null vector.
AssemblyHandler * Assembly_handler_pt
Pointer to the underlying (original) assembly handler.
void get_residuals(GeneralisedElement *const &elem_pt, Vector< double > &residuals)
Get the residuals.
double Sigma
A slack variable used to specify the amount of antisymmetry in the solution.
unsigned Solve_which_system
Integer flag to indicate which system should be assembled. There are three possibilities....
void get_dresiduals_dparameter(GeneralisedElement *const &elem_pt, double *const ¶meter_pt, Vector< double > &dres_dparam)
Overload the derivatives of the residuals with respect to a parameter to apply to the augmented syste...
~PitchForkHandler()
Destructor, return the problem to its original state, before the augmented system was added.
void get_hessian_vector_products(GeneralisedElement *const &elem_pt, Vector< double > const &Y, DenseMatrix< double > const &C, DenseMatrix< double > &product)
Overload the hessian vector product function so that it breaks.
DoubleVectorWithHaloEntries C
A constant vector used to ensure that the null vector is not trivial.
unsigned Ndof
Store the number of degrees of freedom in the non-augmented problem.
PitchForkHandler(Problem *const &problem_pt, AssemblyHandler *const &assembly_handler_pt, double *const ¶meter_pt, const DoubleVector &symmetry_vector)
Constructor, initialise the systems.
void get_eigenfunction(Vector< DoubleVector > &eigenfunction)
Return the eigenfunction(s) associated with the bifurcation that has been detected in bifurcation tra...
DoubleVectorWithHaloEntries Psi
A constant vector that is specifies the symmetry being broken.
double * Parameter_pt
Storage for the pointer to the parameter.
void get_djacobian_dparameter(GeneralisedElement *const &elem_pt, double *const ¶meter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam)
Overload the derivative of the residuals and jacobian with respect to a parameter so that it breaks.
void get_jacobian(GeneralisedElement *const &elem_pt, Vector< double > &residuals, DenseMatrix< double > &jacobian)
Calculate the elemental Jacobian matrix "d equation / d variable".
unsigned long eqn_number(GeneralisedElement *const &elem_pt, const unsigned &ieqn_local)
Get the global equation number of the local unknown.
bool Distributed
Boolean to indicate whether the problem is distributed.
unsigned global_eqn_number(const unsigned &i)
Function that is used to return map the global equations using the simplistic numbering scheme into t...
Vector< unsigned > Global_eqn_number
A vector that is used to map the global equations to their actual location in a distributed problem.
void solve_augmented_block_system()
Set to solve the augmented block system.
void solve_block_system()
Set to solve the block system.
DoubleVectorWithHaloEntries Count
A vector that is used to determine how many elements contribute to a particular equation....
unsigned ndof(GeneralisedElement *const &elem_pt)
Get the number of elemental degrees of freedom.
LinearAlgebraDistribution * Augmented_dof_distribution_pt
The augmented distribution.
////////////////////////////////////////////////////////////////// //////////////////////////////////...
double *& dof_pt(const unsigned &i)
Pointer to i-th dof in the problem.
DoubleVectorHaloScheme * Halo_scheme_pt
Pointer to the halo scheme for any global vectors that have the Dof_distribution.
void setup_dof_halo_scheme()
Function that is used to setup the halo scheme.
unsigned long ndof() const
Return the number of dofs.
AssemblyHandler *& assembly_handler_pt()
Return a pointer to the assembly handler object.
double * global_dof_pt(const unsigned &i)
Return a pointer to the dof, indexed by global equation number which may be haloed or stored locally....
Vector< Vector< unsigned > > Sparse_assemble_with_arrays_previous_allocation
the number of elements in each row of a compressed matrix in the previous matrix assembly.
virtual void actions_after_change_in_bifurcation_parameter()
Actions that are to be performed after a change in the parameter that is being varied as part of the ...
OomphCommunicator * communicator_pt()
access function to the oomph-lib communicator
LinearSolver *& linear_solver_pt()
Return a pointer to the linear solver object.
virtual void get_residuals(DoubleVector &residuals)
Return the fully-assembled residuals Vector for the problem: Virtual so it can be overloaded in for m...
double & dof(const unsigned &i)
i-th dof in the problem
int & sign_of_jacobian()
Access function for the sign of the global jacobian matrix. This will be set by the linear solver,...
Vector< double * > Dof_pt
Vector of pointers to dofs.
Mesh *& mesh_pt()
Return a pointer to the global mesh.
void get_hessian_vector_products(DoubleVectorWithHaloEntries const &Y, Vector< DoubleVectorWithHaloEntries > const &C, Vector< DoubleVectorWithHaloEntries > &product)
Return the product of the global hessian (derivative of Jacobian matrix with respect to all variables...
LinearAlgebraDistribution * Dof_distribution_pt
The distribution of the DOFs in this problem. This object is created in the Problem constructor and s...
virtual void actions_before_newton_convergence_check()
Any actions that are to be performed before the residual is checked in the Newton method,...
void get_derivative_wrt_global_parameter(double *const ¶meter_pt, DoubleVector &result)
Get the derivative of the entire residuals vector wrt a global parameter, used in continuation proble...
bool distributed() const
If we have MPI return the "problem has been distributed" flag, otherwise it can't be distributed so r...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...