63 int n_dof = problem_pt->
ndof();
68 "You can only call this if the problem has just one dof!",
69 OOMPH_CURRENT_FUNCTION,
70 OOMPH_EXCEPTION_LOCATION);
75 double global_jac=0.0;
76 double global_res=0.0;
84 for(
unsigned long e=0;
e<n_el;
e++)
90 int nvar = assembly_handler_pt->
ndof(elem_pt);
100 assembly_handler_pt->
get_jacobian(elem_pt,residuals,jacobian);
103 global_jac+=jacobian(0,0);
104 global_res+=residuals[0];
109 result[0]=global_res/global_jac;
115 if(
W!=0) {
delete[]
W;}
125 static_cast<int>(std::fabs(global_jac)/global_jac);
136 std::ostringstream error_message;
138 <<
"HSL_MA42 solver cannot be used in parallel.\n" 139 <<
"Please change to another linear solver.\n" 140 <<
"If you want to use a frontal solver then try MumpsSolver\n";
143 OOMPH_CURRENT_FUNCTION,
144 OOMPH_EXCEPTION_LOCATION);
178 double cntl[2], rinfo[2];
181 int ndf, nmaxe=2, nrhs=1, lrhs=1;
185 int *last =
new int[n_dof];
187 double **dx =
new double *;
188 *dx =
new double[n_dof];
191 int exact_lenbuf[3]={0,0,0};
192 bool exact_lenbuf_available=
false;
196 int lenbuf0_recommendation=0;
197 int lenbuf1_recommendation=0;
198 int lenbuf2_recommendation=0;
205 int exact_lenfle[3]={0,0,0};
206 bool exact_lenfle_available=
false;
210 int lenfle0_recommendation=0;
211 int lenfle1_recommendation=0;
212 int lenfle2_recommendation=0;
220 double front0_recommendation=0;
221 double front1_recommendation=0;
226 bool exact_nfront_available=
false;
251 for(
unsigned long e=0;
e<n_el;
e++)
260 int nvar = assembly_handler_pt->
ndof(elem_pt);
270 for(
int i=0;
i<nvar;
i++)
273 ivar[
i] = 1 + assembly_handler_pt->
eqn_number(elem_pt,
i);
286 int only_eqn = assembly_handler_pt->
eqn_number(elem_pt,0);
289 ivar[0] = 1 + only_eqn;
293 if (only_eqn!=(n_dof-1))
295 dummy_eqn=only_eqn+1;
299 dummy_eqn=only_eqn-1;
325 for(
unsigned long e=0;
e<n_el;
e++)
334 int nvar = assembly_handler_pt->
ndof(elem_pt);
343 for(
int i=0;
i<nvar;
i++)
346 ivar[
i] = 1 + assembly_handler_pt->
eqn_number(elem_pt,
i);
359 int only_eqn = assembly_handler_pt->
eqn_number(elem_pt,0);
362 ivar[0] = 1 + only_eqn;
366 if (only_eqn!=(n_dof-1))
368 dummy_eqn=only_eqn+1;
372 dummy_eqn=only_eqn-1;
399 front0_recommendation=ifsize[0];
400 front1_recommendation=ifsize[1];
401 if (!exact_nfront_available)
403 nfront[0]=int(ceil(
Front_factor*
double(front0_recommendation)));
404 nfront[1]=int(ceil(
Front_factor*
double(front1_recommendation)));
406 if(n_dof < nfront[0]) nfront[0] = n_dof;
407 if(n_dof < nfront[1]) nfront[1] = n_dof;
414 lenbuf0_recommendation=ifsize[2] + ndf;
419 else {lenbuf1_recommendation=0;}
420 lenbuf2_recommendation=ifsize[4];
429 oomph_info <<
"Using direct access files" << std::endl;
444 lenbuf[0] = int(ceil(factor*
double(10*(nfront[0] + 1))));
447 {lenbuf[1] = int(ceil(factor*
double(10*(nfront[0]))));}
449 else {lenbuf[1] = 0;}
450 lenbuf[2] = int(ceil(factor*
double(10*(2*nfront[0]+5))));
454 if (exact_lenfle_available)
456 lenfle[0] = exact_lenfle[0];
457 lenfle[1] = exact_lenfle[1];
458 lenfle[2] = exact_lenfle[2];
462 lenfle0_recommendation=ifsize[2]+ndf;
463 lenfle1_recommendation=ifsize[3];
464 lenfle2_recommendation=ifsize[4];
465 lenfle[0]=int(ceil(
Lenfle_factor*
double(lenfle0_recommendation)));
466 lenfle[1]=int(ceil(
Lenfle_factor*
double(lenfle1_recommendation)));
467 lenfle[2]=int(ceil(
Lenfle_factor*
double(lenfle2_recommendation)));
477 oomph_info <<
"Not using direct access files" << std::endl;
481 if (exact_lenbuf_available)
483 lenbuf[0] = exact_lenbuf[0];
484 lenbuf[1] = exact_lenbuf[1];
485 lenbuf[2] = exact_lenbuf[2];
489 lenbuf[0] = int(ceil(
Lenbuf_factor0*
double(lenbuf0_recommendation)));
492 {lenbuf[1] = int(ceil(
Lenbuf_factor1*
double(lenbuf1_recommendation)));}
494 else {lenbuf[1] = 0;}
495 lenbuf[2] = int(ceil(
Lenbuf_factor2*
double(lenbuf2_recommendation)));
503 oomph_info <<
"\n FRONT SIZE (min and actual): " 504 << ifsize[0] <<
" " << nfront[0] << std::endl;
512 int lw = 1 + lenbuf[0] + lenbuf[1] + nfront[0]*nfront[1];
513 if(lrhs*nfront[0] > nrhs*nfront[1])
515 lw += lrhs*nfront[0];
519 lw += nrhs*nfront[1];
522 int liw = lenbuf[2] + 2*nfront[0] + 4*nfront[1];
535 W =
new (std::nothrow)
double [
Lw];
539 OOMPH_CURRENT_FUNCTION,
540 OOMPH_EXCEPTION_LOCATION);
550 if(
IW!=0) {
delete[]
IW;}
552 IW =
new (std::nothrow)
int [
Liw];
556 OOMPH_CURRENT_FUNCTION,
557 OOMPH_EXCEPTION_LOCATION);
564 double temp = (lenbuf[0]*
sizeof(double) + lenbuf[2]*
sizeof(
int))/
566 oomph_info <<
"\n ESTIMATED MEMORY USAGE " << temp <<
"Mb" << std::endl;
572 for(
unsigned long e=0;
e<n_el;
e++)
578 int nvar = assembly_handler_pt->
ndof(elem_pt);
590 for(
int i=0;
i<nvar;
i++)
593 ivar[
i] = 1 + assembly_handler_pt->
eqn_number(elem_pt,
i);
607 int only_eqn = assembly_handler_pt->
eqn_number(elem_pt,0);
610 ivar[0] = 1 + only_eqn;
614 if (only_eqn!=(n_dof-1))
616 dummy_eqn=only_eqn+1;
620 dummy_eqn=only_eqn-1;
632 assembly_handler_pt->
get_jacobian(elem_pt,residuals,jacobian);
637 double onlyjac=jacobian(0,0);
639 jacobian(0,0)=onlyjac;
644 double onlyres=residuals[0];
646 residuals[0]=onlyres;
661 double **avar =
new double*[nvar];
662 double *tmp =
new double[nvar*nmaxe];
663 for(
int i=0;
i<nvar;
i++) {avar[
i] = &tmp[
i*nmaxe];}
664 double **rhs =
new double*[1];
665 rhs[0] =
new double[nmaxe];
668 for(
int i=0;
i<nmaxe;
i++)
670 rhs[0][
i] = residuals[
i];
671 for(
int j=0;j<nvar;j++)
674 avar[j][
i] = jacobian(
i,j);
679 MA42BD(nvar,ivar,ndf,last,nmaxe,avar,nrhs,rhs,lrhs,n_dof,dx,nfront,
698 else if (
Info[0]==-12)
703 else if (
Info[0]==-17)
712 oomph_info<<
"Can't recover from this error"<<std::endl;
719 delete[] rhs[0]; rhs[0] = 0;
720 delete[] rhs; rhs =0;
721 delete[] avar[0]; avar[0] = 0;
739 delete[]
W;
W=0;
Lw=0;
756 exact_lenbuf[0] =
Info[4];
757 exact_lenbuf[1] =
Info[5];
758 exact_lenbuf[2] =
Info[6];
759 exact_lenbuf_available=
true;
765 exact_nfront_available=
true;
768 exact_lenfle[0] = lenbuf[0]*
Info[9];
769 exact_lenfle[1] = lenbuf[1]*Info[10];
770 exact_lenfle[2] = lenbuf[2]*Info[11];
771 exact_lenfle_available=
true;
780 for(
int i=0;
i<n_dof;
i++) result[
i] = dx[0][
i];
787 double temp = (
Info[4]*
sizeof(double) +
Info[6]*
sizeof(
int))/
789 oomph_info <<
" TOTAL MEMORY USED " << temp <<
"Mb" << std::endl;
792 oomph_info <<
"lenbuf[]: " << lenbuf[0] <<
" " 793 << lenbuf[1] <<
" " << lenbuf[2] <<
" " << std::endl;
794 oomph_info <<
"lenbuf[] factors required and initially specified:" 796 oomph_info <<
"lenbuf[0]: " <<
Info[4]/double(lenbuf0_recommendation) <<
" " 798 oomph_info <<
"lenbuf[1]: " <<
Info[5]/double(lenbuf1_recommendation)
802 oomph_info <<
"lenbuf[2]: " <<
Info[6]/double(lenbuf2_recommendation) <<
" " 804 oomph_info <<
"nfront[] factors required and initially specified:" 806 oomph_info <<
"nfront[0]: " << nfront[0]/double(front0_recommendation)
808 oomph_info <<
"nfront[1]: " << nfront[1]/double(front1_recommendation)
812 oomph_info <<
"lenfle[]: " << lenfle[0] <<
" " 813 << lenfle[1] <<
" " << lenfle[2] <<
" " << std::endl;
814 oomph_info <<
"lenfle[] factors required and initially specified:" 817 <<
Info[9]*lenbuf[0]/double(lenfle0_recommendation)
820 <<
Info[10]*lenbuf[1]/double(lenfle1_recommendation)
823 <<
Info[11]*lenbuf[2]/double(lenfle2_recommendation)
843 OOMPH_CURRENT_FUNCTION,
844 OOMPH_EXCEPTION_LOCATION);
852 if(n_dof != static_cast<int>(rhs.
nrow()))
855 "RHS does not have the same dimension as the linear system",
856 OOMPH_CURRENT_FUNCTION,
857 OOMPH_EXCEPTION_LOCATION);
863 if(n_dof==1) {result[0]= rhs[0]/
W[0];
return;}
874 double **b =
new double*;
875 *b =
new double[n_dof];
877 for(
int i=0;
i<n_dof;
i++) {b[0][
i] = rhs[
i];}
880 double **x =
new double*;
881 *x =
new double[n_dof];
884 MA42CD(trans,nrhs,lx,b,x,
Lw,
W,
Liw,
IW,
Icntl,
Isave,
Info);
891 for(
int i=0;
i<n_dof;++
i) {result[
i] = x[0][
i];}
910 int n_dof = problem_pt->
ndof();
915 int icntl[10], info[15], direct, nsup, vars[n_dof], svar[n_dof];
916 int liw, lw, *perm=0;
917 double wt[3], rinfo[6];
940 int *iw =
new int [liw];
941 double *w =
new double [lw];
952 for(
unsigned long e=0;
e<n_el;
e++)
961 int nvar = assembly_handler_pt->
ndof(elem_pt);
968 for(
int i=0;
i<nvar;
i++)
971 eltvar.push_back(1 + assembly_handler_pt->
eqn_number(elem_pt,
i));
973 eltptr.push_back(eltptr.back()+nvar);
980 int only_eqn=assembly_handler_pt->
eqn_number(elem_pt,0);
983 eltvar.push_back(1 + only_eqn);
987 if (only_eqn!=(n_dof-1)) {dummy_eqn=only_eqn+1;}
988 else {dummy_eqn=only_eqn-1;}
990 eltvar.push_back(1+dummy_eqn);
992 eltptr.push_back(eltptr.back()+2);
998 int n_e = eltvar.size();
1003 MC63AD(direct,n_dof,n_el,n_e,&eltvar[0],&eltptr[0],&order[0],
1004 perm,nsup,vars,svar,wt,liw,iw,lw,w,icntl,info,rinfo);
1010 << info[4] << std::endl;
1020 << info[5] << std::endl;
1023 w =
new double [lw];
1026 }
while(info[0] < 0);
1031 oomph_info <<
"\n Initial wavefront details :\n max " 1032 << rinfo[0] <<
"\tmean " 1033 << rinfo[1] <<
"\tprofile " << rinfo[2];
1034 oomph_info <<
"\n Reordered wavefront details:\n max " 1035 << rinfo[3] <<
"\tmean " 1036 << rinfo[4] <<
"\tprofile " << rinfo[5];
1048 for (
unsigned e=0;
e<n_el;
e++)
1052 for (
unsigned e=0;
e<n_el;
e++)
A Generalised Element class.
A class to handle errors in the Newton solver.
double Lenbuf_factor2
Factor to increase storage for lenbuf[2]; see MA42 documentation for details.
int Icntl[8]
Control flag for MA42; see MA42 documentation for details.
bool Reorder_flag
Reorder elements with Sloan's algorithm?
bool Doc_stats
Doc the solver stats or stay quiet?
bool Use_direct_access_files
Use direct access files?
unsigned long N_dof
Size of the linear system.
int Liw
Size of the integer workspace array.
bool Enable_resolve
Boolean that indicates whether the matrix (or its factors, in the case of direct solver) should be st...
double Lenbuf_factor0
Factor to increase storage for lenbuf[0]; see MA42 documentation for details.
Mesh *& mesh_pt()
Return a pointer to the global mesh.
OomphCommunicator * communicator_pt()
access function to the oomph-lib communicator
double Lenbuf_factor1
Factor to increase storage for lenbuf[1]; see MA42 documentation for details.
unsigned long nelement() const
Return number of elements in the mesh.
AssemblyHandler *& assembly_handler_pt()
Return a pointer to the assembly handler object.
virtual unsigned ndof(GeneralisedElement *const &elem_pt)
Return the number of degrees of freedom in the element elem_pt.
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
int Info[23]
Control flag for MA42; see MA42 documentation for details.
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
int & sign_of_jacobian()
Access function for the sign of the global jacobian matrix. This will be set by the linear solver...
int * IW
Integer workspace storage for MA42.
void reorder_elements(Problem *const &problem_pt)
Function to reorder the elements based on Sloan's algorithm.
double * W
Workspace storage for MA42.
double Front_factor
Factor to increase storage for front size; see MA42 documentation for details.
A class that is used to define the functions used to assemble the elemental contributions to the resi...
void resolve(const DoubleVector &rhs, DoubleVector &result)
Return the solution to the linear system Ax = result, where A is the most recently factorised jacobia...
unsigned long ndof() const
Return the number of dofs.
unsigned nrow() const
access function to the number of global rows.
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 build_distribution(const LinearAlgebraDistribution *const dist_pt)
setup the distribution of this distributable linear algebra object
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.
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...
double Lenfle_factor
Factor to increase size of direct access files; see MA42 documentation for details.
A vector in the mathematical sense, initially developed for linear algebra type applications. If MPI then this vector can be distributed - its distribution is described by the LinearAlgebraDistribution object at Distribution_pt. Data is stored in a C-style pointer vector (double*)
int Isave[45]
Control flag for MA42; see MA42 documentation for details.
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...
int Lw
Size of the workspace array, W.
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
void resize(const unsigned long &n)