56 int n_dof = problem_pt->
ndof();
61 "You can only call this if the problem has just one dof!",
62 OOMPH_CURRENT_FUNCTION,
63 OOMPH_EXCEPTION_LOCATION);
68 double global_jac = 0.0;
69 double global_res = 0.0;
77 for (
unsigned long e = 0;
e < n_el;
e++)
83 int nvar = assembly_handler_pt->
ndof(elem_pt);
93 assembly_handler_pt->
get_jacobian(elem_pt, residuals, jacobian);
96 global_jac += jacobian(0, 0);
97 global_res += residuals[0];
102 result[0] = global_res / global_jac;
121 static_cast<int>(std::fabs(global_jac) / global_jac);
132 std::ostringstream error_message;
134 <<
"HSL_MA42 solver cannot be used in parallel.\n"
135 <<
"Please change to another linear solver.\n"
136 <<
"If you want to use a frontal solver then try MumpsSolver\n";
139 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
172 double cntl[2], rinfo[2];
175 int ndf, nmaxe = 2, nrhs = 1, lrhs = 1;
179 int* last =
new int[n_dof];
181 double** dx =
new double*;
182 *dx =
new double[n_dof];
185 int exact_lenbuf[3] = {0, 0, 0};
186 bool exact_lenbuf_available =
false;
190 int lenbuf0_recommendation = 0;
191 int lenbuf1_recommendation = 0;
192 int lenbuf2_recommendation = 0;
199 int exact_lenfle[3] = {0, 0, 0};
200 bool exact_lenfle_available =
false;
204 int lenfle0_recommendation = 0;
205 int lenfle1_recommendation = 0;
206 int lenfle2_recommendation = 0;
214 double front0_recommendation = 0;
215 double front1_recommendation = 0;
220 bool exact_nfront_available =
false;
234 bool not_done =
true;
244 for (
unsigned long e = 0;
e < n_el;
e++)
253 int nvar = assembly_handler_pt->
ndof(elem_pt);
261 ivar =
new int[nvar];
263 for (
int i = 0;
i < nvar;
i++)
266 ivar[
i] = 1 + assembly_handler_pt->
eqn_number(elem_pt,
i);
278 int only_eqn = assembly_handler_pt->
eqn_number(elem_pt, 0);
281 ivar[0] = 1 + only_eqn;
285 if (only_eqn != (n_dof - 1))
287 dummy_eqn = only_eqn + 1;
291 dummy_eqn = only_eqn - 1;
293 ivar[1] = 1 + dummy_eqn;
319 for (
unsigned long e = 0;
e < n_el;
e++)
328 int nvar = assembly_handler_pt->
ndof(elem_pt);
335 ivar =
new int[nvar];
337 for (
int i = 0;
i < nvar;
i++)
340 ivar[
i] = 1 + assembly_handler_pt->
eqn_number(elem_pt,
i);
352 int only_eqn = assembly_handler_pt->
eqn_number(elem_pt, 0);
355 ivar[0] = 1 + only_eqn;
359 if (only_eqn != (n_dof - 1))
361 dummy_eqn = only_eqn + 1;
365 dummy_eqn = only_eqn - 1;
367 ivar[1] = 1 + dummy_eqn;
393 front0_recommendation = ifsize[0];
394 front1_recommendation = ifsize[1];
395 if (!exact_nfront_available)
397 nfront[0] = int(ceil(
Front_factor *
double(front0_recommendation)));
398 nfront[1] = int(ceil(
Front_factor *
double(front1_recommendation)));
400 if (n_dof < nfront[0]) nfront[0] = n_dof;
401 if (n_dof < nfront[1]) nfront[1] = n_dof;
408 lenbuf0_recommendation = ifsize[2] + ndf;
413 lenbuf1_recommendation = ifsize[3];
418 lenbuf1_recommendation = 0;
420 lenbuf2_recommendation = ifsize[4];
429 oomph_info <<
"Using direct access files" << std::endl;
450 lenbuf[0] = int(ceil(factor *
double(10 * (nfront[0] + 1))));
454 lenbuf[1] = int(ceil(factor *
double(10 * (nfront[0]))));
461 lenbuf[2] = int(ceil(factor *
double(10 * (2 * nfront[0] + 5))));
465 if (exact_lenfle_available)
467 lenfle[0] = exact_lenfle[0];
468 lenfle[1] = exact_lenfle[1];
469 lenfle[2] = exact_lenfle[2];
473 lenfle0_recommendation = ifsize[2] + ndf;
474 lenfle1_recommendation = ifsize[3];
475 lenfle2_recommendation = ifsize[4];
476 lenfle[0] = int(ceil(
Lenfle_factor *
double(lenfle0_recommendation)));
477 lenfle[1] = int(ceil(
Lenfle_factor *
double(lenfle1_recommendation)));
478 lenfle[2] = int(ceil(
Lenfle_factor *
double(lenfle2_recommendation)));
488 oomph_info <<
"Not using direct access files" << std::endl;
492 if (exact_lenbuf_available)
494 lenbuf[0] = exact_lenbuf[0];
495 lenbuf[1] = exact_lenbuf[1];
496 lenbuf[2] = exact_lenbuf[2];
521 oomph_info <<
"\n FRONT SIZE (min and actual): " << ifsize[0] <<
" "
522 << nfront[0] << std::endl;
530 int lw = 1 + lenbuf[0] + lenbuf[1] + nfront[0] * nfront[1];
531 if (lrhs * nfront[0] > nrhs * nfront[1])
533 lw += lrhs * nfront[0];
537 lw += nrhs * nfront[1];
540 int liw = lenbuf[2] + 2 * nfront[0] + 4 * nfront[1];
553 W =
new (std::nothrow)
double[
Lw];
557 OOMPH_CURRENT_FUNCTION,
558 OOMPH_EXCEPTION_LOCATION);
573 IW =
new (std::nothrow)
int[
Liw];
577 OOMPH_CURRENT_FUNCTION,
578 OOMPH_EXCEPTION_LOCATION);
585 double temp = (lenbuf[0] *
sizeof(double) + lenbuf[2] *
sizeof(
int)) /
587 oomph_info <<
"\n ESTIMATED MEMORY USAGE " << temp <<
"Mb" << std::endl;
593 for (
unsigned long e = 0;
e < n_el;
e++)
599 int nvar = assembly_handler_pt->
ndof(elem_pt);
609 ivar =
new int[nvar];
611 for (
int i = 0;
i < nvar;
i++)
614 ivar[
i] = 1 + assembly_handler_pt->
eqn_number(elem_pt,
i);
627 int only_eqn = assembly_handler_pt->
eqn_number(elem_pt, 0);
630 ivar[0] = 1 + only_eqn;
634 if (only_eqn != (n_dof - 1))
636 dummy_eqn = only_eqn + 1;
640 dummy_eqn = only_eqn - 1;
642 ivar[1] = 1 + dummy_eqn;
652 assembly_handler_pt->
get_jacobian(elem_pt, residuals, jacobian);
657 double onlyjac = jacobian(0, 0);
659 jacobian(0, 0) = onlyjac;
660 jacobian(1, 0) = 0.0;
661 jacobian(0, 1) = 0.0;
662 jacobian(1, 1) = 0.0;
664 double onlyres = residuals[0];
666 residuals[0] = onlyres;
681 double** avar =
new double*[nvar];
682 double* tmp =
new double[nvar * nmaxe];
683 for (
int i = 0;
i < nvar;
i++)
685 avar[
i] = &tmp[
i * nmaxe];
687 double** rhs =
new double*[1];
688 rhs[0] =
new double[nmaxe];
691 for (
int i = 0;
i < nmaxe;
i++)
693 rhs[0][
i] = residuals[
i];
694 for (
int j = 0; j < nvar; j++)
697 avar[j][
i] = jacobian(
i, j);
739 oomph_info <<
"lenbuf[] too small -- can recover..."
742 else if (
Info[0] == -12)
745 oomph_info <<
"nfront[] too small -- can recover..."
748 else if (
Info[0] == -17)
751 oomph_info <<
"lenfle[] too small -- can recover..."
758 oomph_info <<
"Can't recover from this error" << std::endl;
809 exact_lenbuf[0] =
Info[4];
810 exact_lenbuf[1] =
Info[5];
811 exact_lenbuf[2] =
Info[6];
812 exact_lenbuf_available =
true;
818 exact_nfront_available =
true;
821 exact_lenfle[0] = lenbuf[0] *
Info[9];
822 exact_lenfle[1] = lenbuf[1] *
Info[10];
823 exact_lenfle[2] = lenbuf[2] *
Info[11];
824 exact_lenfle_available =
true;
832 for (
int i = 0;
i < n_dof;
i++) result[
i] = dx[0][
i];
839 double temp = (
Info[4] *
sizeof(double) +
Info[6] *
sizeof(
int)) /
841 oomph_info <<
" TOTAL MEMORY USED " << temp <<
"Mb" << std::endl;
844 oomph_info <<
"lenbuf[]: " << lenbuf[0] <<
" " << lenbuf[1] <<
" "
845 << lenbuf[2] <<
" " << std::endl;
846 oomph_info <<
"lenbuf[] factors required and initially specified:"
848 oomph_info <<
"lenbuf[0]: " <<
Info[4] / double(lenbuf0_recommendation)
850 oomph_info <<
"lenbuf[1]: " <<
Info[5] / double(lenbuf1_recommendation)
853 oomph_info <<
"lenbuf[2]: " <<
Info[6] / double(lenbuf2_recommendation)
855 oomph_info <<
"nfront[] factors required and initially specified:"
857 oomph_info <<
"nfront[0]: " << nfront[0] / double(front0_recommendation)
859 oomph_info <<
"nfront[1]: " << nfront[1] / double(front1_recommendation)
863 oomph_info <<
"lenfle[]: " << lenfle[0] <<
" " << lenfle[1] <<
" "
864 << lenfle[2] <<
" " << std::endl;
865 oomph_info <<
"lenfle[] factors required and initially specified:"
868 <<
Info[9] * lenbuf[0] / double(lenfle0_recommendation)
871 <<
Info[10] * lenbuf[1] / double(lenfle1_recommendation)
874 <<
Info[11] * lenbuf[2] / double(lenfle2_recommendation)
894 OOMPH_CURRENT_FUNCTION,
895 OOMPH_EXCEPTION_LOCATION);
903 if (n_dof !=
static_cast<int>(rhs.
nrow()))
906 "RHS does not have the same dimension as the linear system",
907 OOMPH_CURRENT_FUNCTION,
908 OOMPH_EXCEPTION_LOCATION);
916 result[0] = rhs[0] /
W[0];
930 double** b =
new double*;
931 *b =
new double[n_dof];
933 for (
int i = 0;
i < n_dof;
i++)
939 double** x =
new double*;
940 *x =
new double[n_dof];
943 MA42CD(trans, nrhs, lx, b, x,
Lw,
W,
Liw,
IW,
Icntl,
Isave,
Info);
953 for (
int i = 0;
i < n_dof; ++
i)
975 int n_dof = problem_pt->
ndof();
980 int icntl[10], info[15], direct, nsup, vars[n_dof], svar[n_dof];
981 int liw, lw, *perm = 0;
982 double wt[3], rinfo[6];
1005 int* iw =
new int[liw];
1006 double* w =
new double[lw];
1017 for (
unsigned long e = 0;
e < n_el;
e++)
1026 int nvar = assembly_handler_pt->
ndof(elem_pt);
1033 for (
int i = 0;
i < nvar;
i++)
1036 eltvar.push_back(1 + assembly_handler_pt->
eqn_number(elem_pt,
i));
1038 eltptr.push_back(eltptr.back() + nvar);
1045 int only_eqn = assembly_handler_pt->
eqn_number(elem_pt, 0);
1048 eltvar.push_back(1 + only_eqn);
1052 if (only_eqn != (n_dof - 1))
1054 dummy_eqn = only_eqn + 1;
1058 dummy_eqn = only_eqn - 1;
1061 eltvar.push_back(1 + dummy_eqn);
1063 eltptr.push_back(eltptr.back() + 2);
1069 int n_e = eltvar.size();
1098 oomph_info <<
" Reallocating liw to " << info[4] << std::endl;
1108 oomph_info <<
" Reallocating lw to " << info[5] << std::endl;
1114 }
while (info[0] < 0);
1119 oomph_info <<
"\n Initial wavefront details :\n max " << rinfo[0]
1120 <<
"\tmean " << rinfo[1] <<
"\tprofile " << rinfo[2];
1121 oomph_info <<
"\n Reordered wavefront details:\n max " << rinfo[3]
1122 <<
"\tmean " << rinfo[4] <<
"\tprofile " << rinfo[5];
1133 for (
unsigned e = 0;
e < n_el;
e++)
1137 for (
unsigned e = 0;
e < n_el;
e++)
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 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 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.
void resize(const unsigned long &n)
Resize to a square nxn matrix; any values already present will be transfered.
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
unsigned nrow() const
access function to the number of global rows.
void build_distribution(const LinearAlgebraDistribution *const dist_pt)
setup the distribution of this distributable linear algebra object
A vector in the mathematical sense, initially developed for linear algebra type applications....
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
A Generalised Element class.
int Lw
Size of the workspace array, W.
bool Doc_stats
Doc the solver stats or stay quiet?
double Lenfle_factor
Factor to increase size of direct access files; see MA42 documentation for details.
bool Use_direct_access_files
Use direct access files?
bool Reorder_flag
Reorder elements with Sloan's algorithm?
double Lenbuf_factor2
Factor to increase storage for lenbuf[2]; see MA42 documentation for details.
double Lenbuf_factor1
Factor to increase storage for lenbuf[1]; see MA42 documentation for details.
int Icntl[8]
Control flag for MA42; see MA42 documentation for details.
int Isave[45]
Control flag for MA42; see MA42 documentation for details.
int Liw
Size of the integer workspace array.
void reorder_elements(Problem *const &problem_pt)
Function to reorder the elements based on Sloan's algorithm.
void solve_for_one_dof(Problem *const &problem_pt, DoubleVector &result)
Special solver for problems with 1 dof (MA42 can't handle this case so solve() forwards the "solve" t...
double Front_factor
Factor to increase storage for front size; see MA42 documentation for details.
int Info[23]
Control flag for MA42; see MA42 documentation for details.
double * W
Workspace storage for MA42.
void resolve(const DoubleVector &rhs, DoubleVector &result)
Return the solution to the linear system Ax = result, where A is the most recently factorised jacobia...
double Lenbuf_factor0
Factor to increase storage for lenbuf[0]; see MA42 documentation for details.
void solve(Problem *const &problem_pt, DoubleVector &result)
Solver: Takes pointer to problem and returns the results Vector which contains the solution of the li...
int * IW
Integer workspace storage for MA42.
unsigned long N_dof
Size of the linear system.
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
bool Enable_resolve
Boolean that indicates whether the matrix (or its factors, in the case of direct solver) should be st...
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
unsigned long nelement() const
Return number of elements in the mesh.
A class to handle errors in the Newton solver.
An OomphLibError object which should be thrown when an run-time error is encountered....
////////////////////////////////////////////////////////////////// //////////////////////////////////...
unsigned long ndof() const
Return the number of dofs.
AssemblyHandler *& assembly_handler_pt()
Return a pointer to the assembly handler object.
OomphCommunicator * communicator_pt()
access function to the oomph-lib communicator
int & sign_of_jacobian()
Access function for the sign of the global jacobian matrix. This will be set by the linear solver,...
Mesh *& mesh_pt()
Return a pointer to the global mesh.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...