oomph::HSL_MA42 Class Reference

#include <frontal_solver.h>

+ Inheritance diagram for oomph::HSL_MA42:

Public Member Functions

 HSL_MA42 ()
 
 ~HSL_MA42 ()
 Destructor, clean up the allocated memory. More...
 
 HSL_MA42 (const HSL_MA42 &)=delete
 Broken copy constructor. More...
 
void operator= (const HSL_MA42 &)=delete
 Broken assignment operator. More...
 
void clean_up_memory ()
 Clean up memory. More...
 
void disable_resolve ()
 Overload disable resolve so that it cleans up memory too. More...
 
void solve (Problem *const &problem_pt, DoubleVector &result)
 Wrapper for HSL MA42 frontal solver. More...
 
void solve (DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &result)
 
void solve (DoubleMatrixBase *const &matrix_pt, const Vector< double > &rhs, Vector< double > &result)
 
void resolve (const DoubleVector &rhs, DoubleVector &result)
 Wrapper for HSL MA42 frontal solver. More...
 
void reorder_elements (Problem *const &problem_pt)
 Function to reorder the elements based on Sloan's algorithm. More...
 
void enable_doc_stats ()
 Enable documentation of statistics. More...
 
void disable_doc_stats ()
 Disable documentation of statistics. More...
 
void enable_reordering ()
 Enable reordering using Sloan's algorithm. More...
 
void disable_reordering ()
 Disable reordering. More...
 
void enable_direct_access_files ()
 Enable use of direct access files. More...
 
void disable_direct_access_files ()
 Disable use of direct access files. More...
 
double & lenbuf_factor0 ()
 
double & lenbuf_factor1 ()
 
double & lenbuf_factor2 ()
 
double & front_factor ()
 
double & lenfle_factor ()
 
- Public Member Functions inherited from oomph::LinearSolver
 LinearSolver ()
 Empty constructor, initialise the member data. More...
 
 LinearSolver (const LinearSolver &dummy)=delete
 Broken copy constructor. More...
 
void operator= (const LinearSolver &)=delete
 Broken assignment operator. More...
 
virtual ~LinearSolver ()
 Empty virtual destructor. More...
 
void enable_doc_time ()
 Enable documentation of solve times. More...
 
void disable_doc_time ()
 Disable documentation of solve times. More...
 
bool is_doc_time_enabled () const
 Is documentation of solve times enabled? More...
 
bool is_resolve_enabled () const
 Boolean flag indicating if resolves are enabled. More...
 
virtual void enable_resolve ()
 
virtual void solve_transpose (Problem *const &problem_pt, DoubleVector &result)
 
virtual void solve_transpose (DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &result)
 
virtual void solve_transpose (DoubleMatrixBase *const &matrix_pt, const Vector< double > &rhs, Vector< double > &result)
 
virtual void resolve_transpose (const DoubleVector &rhs, DoubleVector &result)
 
virtual double jacobian_setup_time () const
 
virtual double linear_solver_solution_time () const
 
virtual void enable_computation_of_gradient ()
 
void disable_computation_of_gradient ()
 
void reset_gradient ()
 
void get_gradient (DoubleVector &gradient)
 function to access the gradient, provided it has been computed More...
 
- Public Member Functions inherited from oomph::DistributableLinearAlgebraObject
 DistributableLinearAlgebraObject ()
 Default constructor - create a distribution. More...
 
 DistributableLinearAlgebraObject (const DistributableLinearAlgebraObject &matrix)=delete
 Broken copy constructor. More...
 
void operator= (const DistributableLinearAlgebraObject &)=delete
 Broken assignment operator. More...
 
virtual ~DistributableLinearAlgebraObject ()
 Destructor. More...
 
LinearAlgebraDistribution * distribution_pt () const
 access to the LinearAlgebraDistribution More...
 
unsigned nrow () const
 access function to the number of global rows. More...
 
unsigned nrow_local () const
 access function for the num of local rows on this processor. More...
 
unsigned nrow_local (const unsigned &p) const
 access function for the num of local rows on this processor. More...
 
unsigned first_row () const
 access function for the first row on this processor More...
 
unsigned first_row (const unsigned &p) const
 access function for the first row on this processor More...
 
bool distributed () const
 distribution is serial or distributed More...
 
bool distribution_built () const
 
void build_distribution (const LinearAlgebraDistribution *const dist_pt)
 
void build_distribution (const LinearAlgebraDistribution &dist)
 

Private Member Functions

void solve_for_one_dof (Problem *const &problem_pt, DoubleVector &result)
 

Private Attributes

bool Doc_stats
 Doc the solver stats or stay quiet? More...
 
bool Reorder_flag
 Reorder elements with Sloan's algorithm? More...
 
bool Use_direct_access_files
 Use direct access files? More...
 
double Lenbuf_factor0
 
double Lenbuf_factor1
 
double Lenbuf_factor2
 
double Front_factor
 
double Lenfle_factor
 
int Icntl [8]
 Control flag for MA42; see MA42 documentation for details. More...
 
int Isave [45]
 Control flag for MA42; see MA42 documentation for details. More...
 
int Info [23]
 Control flag for MA42; see MA42 documentation for details. More...
 
double * W
 Workspace storage for MA42. More...
 
int Lw
 Size of the workspace array, W. More...
 
int * IW
 Integer workspace storage for MA42. More...
 
int Liw
 Size of the integer workspace array. More...
 
unsigned long N_dof
 Size of the linear system. More...
 

Additional Inherited Members

- Protected Member Functions inherited from oomph::DistributableLinearAlgebraObject
void clear_distribution ()
 
- Protected Attributes inherited from oomph::LinearSolver
bool Enable_resolve
 
bool Doc_time
 Boolean flag that indicates whether the time taken. More...
 
bool Compute_gradient
 
bool Gradient_has_been_computed
 flag that indicates whether the gradient was computed or not More...
 
DoubleVector Gradient_for_glob_conv_newton_solve
 

Detailed Description

Linear solver class that provides a wrapper to the frontal solver MA42 from the HSL library; see http://www.hsl.rl.ac.uk/.

Constructor & Destructor Documentation

◆ HSL_MA42() [1/2]

oomph::HSL_MA42::HSL_MA42 ( )
inline

Constructor: By default suppress verbose output (stats), don't reorder elements and don't use direct access files

119  : W(0), Lw(0), IW(0), Liw(0), N_dof(0)
120  {
121  Doc_stats = false;
122  Reorder_flag = false;
123  Use_direct_access_files = false;
124 
125  // Default values for memory allocation
126  Lenbuf_factor0 = 1.2;
127  Lenbuf_factor1 = 1.2;
128  Lenbuf_factor2 = 1.5;
129  Front_factor = 1.1;
130  Lenfle_factor = 1.5;
131  }
int Lw
Size of the workspace array, W.
Definition: frontal_solver.h:105
bool Doc_stats
Doc the solver stats or stay quiet?
Definition: frontal_solver.h:64
double Lenfle_factor
Definition: frontal_solver.h:90
bool Use_direct_access_files
Use direct access files?
Definition: frontal_solver.h:70
bool Reorder_flag
Reorder elements with Sloan's algorithm?
Definition: frontal_solver.h:67
double Lenbuf_factor2
Definition: frontal_solver.h:82
double Lenbuf_factor1
Definition: frontal_solver.h:78
int Liw
Size of the integer workspace array.
Definition: frontal_solver.h:111
double Front_factor
Definition: frontal_solver.h:86
double * W
Workspace storage for MA42.
Definition: frontal_solver.h:102
double Lenbuf_factor0
Definition: frontal_solver.h:74
int * IW
Integer workspace storage for MA42.
Definition: frontal_solver.h:108
unsigned long N_dof
Size of the linear system.
Definition: frontal_solver.h:114

References Doc_stats, Front_factor, Lenbuf_factor0, Lenbuf_factor1, Lenbuf_factor2, Lenfle_factor, Reorder_flag, and Use_direct_access_files.

◆ ~HSL_MA42()

oomph::HSL_MA42::~HSL_MA42 ( )
inline

Destructor, clean up the allocated memory.

135  {
136  clean_up_memory();
137  }
void clean_up_memory()
Clean up memory.
Definition: frontal_solver.h:146

References clean_up_memory().

◆ HSL_MA42() [2/2]

oomph::HSL_MA42::HSL_MA42 ( const HSL_MA42 &  )
delete

Broken copy constructor.

Member Function Documentation

◆ clean_up_memory()

void oomph::HSL_MA42::clean_up_memory ( )
inlinevirtual

Clean up memory.

Reimplemented from oomph::LinearSolver.

147  {
148  if (IW)
149  {
150  delete[] IW;
151  IW = 0;
152  Liw = 0;
153  }
154  if (W)
155  {
156  delete[] W;
157  W = 0;
158  Lw = 0;
159  }
160  }

References IW, Liw, Lw, and W.

Referenced by disable_resolve(), and ~HSL_MA42().

◆ disable_direct_access_files()

void oomph::HSL_MA42::disable_direct_access_files ( )
inline

Disable use of direct access files.

238  {
239  Use_direct_access_files = false;
240  }

References Use_direct_access_files.

◆ disable_doc_stats()

void oomph::HSL_MA42::disable_doc_stats ( )
inline

Disable documentation of statistics.

214  {
215  Doc_stats = false;
216  }

References Doc_stats.

◆ disable_reordering()

void oomph::HSL_MA42::disable_reordering ( )
inline

Disable reordering.

226  {
227  Reorder_flag = false;
228  }

References Reorder_flag.

◆ disable_resolve()

void oomph::HSL_MA42::disable_resolve ( )
inlinevirtual

Overload disable resolve so that it cleans up memory too.

Reimplemented from oomph::LinearSolver.

164  {
166  clean_up_memory();
167  }
virtual void disable_resolve()
Definition: linear_solver.h:144

References clean_up_memory(), and oomph::LinearSolver::disable_resolve().

◆ enable_direct_access_files()

void oomph::HSL_MA42::enable_direct_access_files ( )
inline

Enable use of direct access files.

232  {
234  }

References Use_direct_access_files.

◆ enable_doc_stats()

void oomph::HSL_MA42::enable_doc_stats ( )
inline

Enable documentation of statistics.

208  {
209  Doc_stats = true;
210  }

References Doc_stats.

◆ enable_reordering()

void oomph::HSL_MA42::enable_reordering ( )
inline

Enable reordering using Sloan's algorithm.

220  {
221  Reorder_flag = true;
222  }

References Reorder_flag.

◆ front_factor()

double& oomph::HSL_MA42::front_factor ( )
inline

Factor to increase storage for front size; see MA42 documentation for details.

266  {
267  return Front_factor;
268  }

References Front_factor.

◆ lenbuf_factor0()

double& oomph::HSL_MA42::lenbuf_factor0 ( )
inline

Factor to increase storage for lenbuf[0]; see MA42 documentation for details.

245  {
246  return Lenbuf_factor0;
247  }

References Lenbuf_factor0.

◆ lenbuf_factor1()

double& oomph::HSL_MA42::lenbuf_factor1 ( )
inline

Factor to increase storage for lenbuf[1]; see MA42 documentation for details.

252  {
253  return Lenbuf_factor1;
254  }

References Lenbuf_factor1.

◆ lenbuf_factor2()

double& oomph::HSL_MA42::lenbuf_factor2 ( )
inline

Factor to increase storage for lenbuf[2]; see MA42 documentation for details.

259  {
260  return Lenbuf_factor2;
261  }

References Lenbuf_factor2.

◆ lenfle_factor()

double& oomph::HSL_MA42::lenfle_factor ( )
inline

Factor to increase the size of the direct access files; see MA42 documentation for details.

273  {
274  return Lenfle_factor;
275  }

References Lenfle_factor.

◆ operator=()

void oomph::HSL_MA42::operator= ( const HSL_MA42 &  )
delete

Broken assignment operator.

◆ reorder_elements()

void oomph::HSL_MA42::reorder_elements ( Problem *const &  problem_pt)

Function to reorder the elements based on Sloan's algorithm.

Function to reorder the elements according to Sloan's algorithm.

970  {
971  // Find the number of elements
972  unsigned long n_el = problem_pt->mesh_pt()->nelement();
973 
974  // Find the number of dofs
975  int n_dof = problem_pt->ndof();
976 
977  Vector<int> order(n_el);
978 
979  // Control parameters
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];
983 
984 
985  // Direct ordering: 1
986  direct = 1;
987 
988  // Initial guess for workspaces (deliberately too small so the
989  // routine fails and returns the required sizes
990  liw = 1;
991  lw = 1;
992 
993  // Initialise things here
994  MC63ID(icntl);
995 
996 
997  // Suppress printing of error and warning messages?
998  if (!Doc_stats)
999  {
1000  icntl[0] = -1;
1001  icntl[1] = -1;
1002  }
1003 
1004  // Set up iw and w
1005  int* iw = new int[liw];
1006  double* w = new double[lw];
1007 
1008  // Set up the vectors that hold the element connectivity information
1009  // Can initialise the first entry of eltptr to 1
1010  Vector<int> eltvar, eltptr(1, 1);
1011 
1012  // Locally cache pointer to assembly handler
1013  AssemblyHandler* const assembly_handler_pt =
1014  problem_pt->assembly_handler_pt();
1015 
1016  // Now loop over all the elements and assemble eltvar and eltptr
1017  for (unsigned long e = 0; e < n_el; e++)
1018  {
1019  // Set up the default order
1020  order[e] = e;
1021 
1022  // Get pointer to the element
1023  GeneralisedElement* elem_pt = problem_pt->mesh_pt()->element_pt(e);
1024 
1025  // Get the number of variables in the element via the assembly handler
1026  int nvar = assembly_handler_pt->ndof(elem_pt);
1027 
1028  // Multiple equations
1029  //-------------------
1030  if (nvar != 1)
1031  {
1032  // Copy the equation numbers into the global array
1033  for (int i = 0; i < nvar; i++)
1034  {
1035  // Need to add one to equation numbers
1036  eltvar.push_back(1 + assembly_handler_pt->eqn_number(elem_pt, i));
1037  }
1038  eltptr.push_back(eltptr.back() + nvar);
1039  }
1040  // Just one equation
1041  //------------------
1042  else
1043  {
1044  // Here's the number of the only equation
1045  int only_eqn = assembly_handler_pt->eqn_number(elem_pt, 0);
1046 
1047  // Need to add one to equation numbers
1048  eltvar.push_back(1 + only_eqn);
1049 
1050  // Now add a dummy eqn either before or after the current one
1051  int dummy_eqn;
1052  if (only_eqn != (n_dof - 1))
1053  {
1054  dummy_eqn = only_eqn + 1;
1055  }
1056  else
1057  {
1058  dummy_eqn = only_eqn - 1;
1059  }
1060 
1061  eltvar.push_back(1 + dummy_eqn);
1062 
1063  eltptr.push_back(eltptr.back() + 2);
1064  }
1065 
1066  } // End of loop over the elements
1067 
1068  // Set the value of n_e (number of entries in the element variable list
1069  int n_e = eltvar.size();
1070 
1071  do
1072  {
1073  // Call the reordering routine
1074  MC63AD(direct,
1075  n_dof,
1076  n_el,
1077  n_e,
1078  &eltvar[0],
1079  &eltptr[0],
1080  &order[0],
1081  perm,
1082  nsup,
1083  vars,
1084  svar,
1085  wt,
1086  liw,
1087  iw,
1088  lw,
1089  w,
1090  icntl,
1091  info,
1092  rinfo);
1093 
1094  // If not enough space in iw or w, allocate enough and try again
1095  if (info[0] == -4)
1096  {
1097  if (Doc_stats)
1098  oomph_info << " Reallocating liw to " << info[4] << std::endl;
1099  delete[] iw;
1100  liw = info[4];
1101  iw = new int[liw];
1102  }
1103 
1104  // If not enough space in w, allocate enough and try again
1105  if (info[0] == -2)
1106  {
1107  if (Doc_stats)
1108  oomph_info << " Reallocating lw to " << info[5] << std::endl;
1109  delete[] w;
1110  lw = info[5];
1111  w = new double[lw];
1112  }
1113 
1114  } while (info[0] < 0);
1115 
1116 
1117  if (Doc_stats)
1118  {
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];
1123  oomph_info << std::endl;
1124  }
1125 
1126  // Free the memory allocated
1127  delete[] w;
1128  delete[] iw;
1129 
1130 
1131  // Store re-ordered elements in temporary vector
1132  Vector<GeneralisedElement*> tmp_element_pt(n_el);
1133  for (unsigned e = 0; e < n_el; e++)
1134  {
1135  tmp_element_pt[e] = problem_pt->mesh_pt()->element_pt(order[e] - 1);
1136  }
1137  for (unsigned e = 0; e < n_el; e++)
1138  {
1139  problem_pt->mesh_pt()->element_pt(e) = tmp_element_pt[e];
1140  }
1141  }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Array< double, 1, 3 > e(1./3., 0.5, 2.)
RowVector3d w
Definition: Matrix_resize_int.cpp:3
#define MC63ID(ICNTL)
#define MC63AD(DIRECT, N, NELT, NE, ELTVAR, ELTPTR, ORDER, PERM, NSUP, VARS, SVAR, WT, LIW, IW, LW, W, ICNTL, INFO, RINFO)
Definition: frontal.h:252
int info
Definition: level2_cplx_impl.h:39
OomphInfo oomph_info
Definition: oomph_definitions.cc:319

References oomph::Problem::assembly_handler_pt(), Doc_stats, e(), oomph::Mesh::element_pt(), oomph::AssemblyHandler::eqn_number(), i, info, MC63AD, MC63ID, oomph::Problem::mesh_pt(), oomph::Problem::ndof(), oomph::AssemblyHandler::ndof(), oomph::Mesh::nelement(), oomph::oomph_info, and w.

Referenced by solve().

◆ resolve()

void oomph::HSL_MA42::resolve ( const DoubleVector &  rhs,
DoubleVector &  result 
)
virtual

Wrapper for HSL MA42 frontal solver.

Return the solution to the linear system Ax = result, where A is the most recently factorised jacobian matrix of the problem problem_pt. The solution is returned in the result vector.

Reimplemented from oomph::LinearSolver.

889  {
890  // If we haven't stored the factors complain
891  if (W == 0)
892  {
893  throw OomphLibError("Resolve called without first solving",
896  }
897 
898  // Find the number of dofs (variables)
899  int n_dof = N_dof;
900 
901  // Check that the number of DOFs is equal to the size of the RHS vector
902 #ifdef PARANOID
903  if (n_dof != static_cast<int>(rhs.nrow()))
904  {
905  throw OomphLibError(
906  "RHS does not have the same dimension as the linear system",
909  }
910 #endif
911 
912  // Special case: just one variable! MA42 can't handle it
913  // Solve using the stored jacobian (single double)
914  if (n_dof == 1)
915  {
916  result[0] = rhs[0] / W[0];
917  return;
918  }
919 
920  // Otherwise actually call the MA42 routine
921  // We are solving the original matrix (not the transpose)
922  int trans = 0;
923  // There is only one rhs
924  int nrhs = 1;
925  // The size of the vectors is the number of degrees of freedom in the
926  // problem
927  int lx = n_dof;
928 
929  // Allocate storage for the RHS
930  double** b = new double*;
931  *b = new double[n_dof];
932  // Load in the RHS vector
933  for (int i = 0; i < n_dof; i++)
934  {
935  b[0][i] = rhs[i];
936  }
937 
938  // Storage for the results
939  double** x = new double*;
940  *x = new double[n_dof];
941 
942  // Now call the resolver
943  MA42CD(trans, nrhs, lx, b, x, Lw, W, Liw, IW, Icntl, Isave, Info);
944 
945  // If there has been an error throw it
946  if (Info[0] < 0)
947  {
948  throw NewtonSolverError(true);
949  }
950 
951  result.build(this->distribution_pt());
952  // Put the answer into the result array
953  for (int i = 0; i < n_dof; ++i)
954  {
955  result[i] = x[0][i];
956  }
957 
958  // Delete the allocated storage
959  delete[] * x;
960  delete x;
961  delete[] * b;
962  delete b;
963  }
Scalar * b
Definition: benchVecAdd.cpp:17
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
Definition: linear_algebra_distribution.h:457
int Icntl[8]
Control flag for MA42; see MA42 documentation for details.
Definition: frontal_solver.h:93
int Isave[45]
Control flag for MA42; see MA42 documentation for details.
Definition: frontal_solver.h:96
int Info[23]
Control flag for MA42; see MA42 documentation for details.
Definition: frontal_solver.h:99
#define MA42CD(TRANS, NRHS, LX, B, X, LW, W, LIW, IW, ICNTL, ISAVE, INFO)
char * trans
Definition: level2_impl.h:240
const double lx
Definition: ConstraintElementsUnitTest.cpp:33
list x
Definition: plotDoE.py:28
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86

References b, oomph::DoubleVector::build(), oomph::DistributableLinearAlgebraObject::distribution_pt(), i, Icntl, Info, Isave, IW, Liw, Lw, Mesh_Parameters::lx, MA42CD, N_dof, oomph::DistributableLinearAlgebraObject::nrow(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, trans, W, and plotDoE::x.

◆ solve() [1/3]

void oomph::HSL_MA42::solve ( DoubleMatrixBase *const &  matrix_pt,
const DoubleVector &  rhs,
DoubleVector &  result 
)
inlinevirtual

Linear-algebra-type solver: Takes pointer to a matrix and rhs vector and returns the solution of the linear system. Call the broken base-class version. If you want this, please implement it

Reimplemented from oomph::LinearSolver.

181  {
182  LinearSolver::solve(matrix_pt, rhs, result);
183  }
virtual void solve(Problem *const &problem_pt, DoubleVector &result)=0

References oomph::LinearSolver::solve().

◆ solve() [2/3]

void oomph::HSL_MA42::solve ( DoubleMatrixBase *const &  matrix_pt,
const Vector< double > &  rhs,
Vector< double > &  result 
)
inlinevirtual

Linear-algebra-type solver: Takes pointer to a matrix and rhs vector and returns the solution of the linear system Call the broken base-class version. If you want this, please implement it

Reimplemented from oomph::LinearSolver.

193  {
194  LinearSolver::solve(matrix_pt, rhs, result);
195  }

References oomph::LinearSolver::solve().

◆ solve() [3/3]

void oomph::HSL_MA42::solve ( Problem *const &  problem_pt,
DoubleVector &  result 
)
virtual

Wrapper for HSL MA42 frontal solver.

Solver: Takes pointer to problem and returns the results Vector which contains the solution of the linear system defined by the problem's fully assembled Jacobian and residual Vector.

Implements oomph::LinearSolver.

128  {
129 #ifdef OOMPH_HAS_MPI
130  if (problem_pt->communicator_pt()->nproc() > 1)
131  {
132  std::ostringstream error_message;
133  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";
137 
138  throw OomphLibError(
139  error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
140  }
141 #endif
142 
143 
144  // Find the number of elements
145  unsigned long n_el = problem_pt->mesh_pt()->nelement();
146 
147  // Find the number of dofs (variables) and store for resolves
148  N_dof = problem_pt->ndof();
149 
150  // Build the distribution .. this is a serial solver
151  LinearAlgebraDistribution dist(problem_pt->communicator_pt(), N_dof, false);
152  this->build_distribution(dist);
153 
154  // Cast the number of dofs into an integer for the HSL solver
155  int n_dof = N_dof;
156 
157  // Special case: Just one variable! MA42 can't handle that
158  if (n_dof == 1)
159  {
160  solve_for_one_dof(problem_pt, result);
161  return;
162  }
163 
164  // Reorder?
165  if (this->Reorder_flag)
166  {
167  reorder_elements(problem_pt);
168  }
169 
170  // Set the control flags
171  int ifsize[5];
172  double cntl[2], rinfo[2];
173 
174  // Set up memory for last and for ndf
175  int ndf, nmaxe = 2, nrhs = 1, lrhs = 1;
176 
177  // Memory for last and dx should be allocated dynamically from the heap
178  // rather than the stack, otherwise one gets a nasty segmentation fault
179  int* last = new int[n_dof];
180  // Set up memory for dx
181  double** dx = new double*;
182  *dx = new double[n_dof];
183 
184  // Provide storage for exact values required for lenbuf array
185  int exact_lenbuf[3] = {0, 0, 0};
186  bool exact_lenbuf_available = false;
187 
188  // Storage for recommendations for lenbuf so we can check how
189  // close our factors are
190  int lenbuf0_recommendation = 0;
191  int lenbuf1_recommendation = 0;
192  int lenbuf2_recommendation = 0;
193 
194  // Provide storage
195  int lenbuf[3];
196 
197 
198  // Provide storage for exact values required for lenfle array
199  int exact_lenfle[3] = {0, 0, 0};
200  bool exact_lenfle_available = false;
201 
202  // Storage for recommendation for lenfle so we can check how
203  // close our factor is
204  int lenfle0_recommendation = 0;
205  int lenfle1_recommendation = 0;
206  int lenfle2_recommendation = 0;
207 
208  // Provide storage
209  int lenfle[3];
210 
211 
212  // Storage for recommendations for front size so we can check how
213  // close our factors are
214  double front0_recommendation = 0;
215  double front1_recommendation = 0;
216 
217 
218  // Flag to indicate if exact, required values for nfront are available
219  // from previous unsucessful solve
220  bool exact_nfront_available = false;
221 
222  // Storage for front sizes
223  int nfront[2];
224 
225  // Locally cache pointer to assembly handler
226  AssemblyHandler* const assembly_handler_pt =
227  problem_pt->assembly_handler_pt();
228 
229 
230  // Loop over size allocation/solver until we've made all the arrays
231  //=================================================================
232  // big enough...
233  //==============
234  bool not_done = true;
235  while (not_done)
236  {
237  // Initialise frontal solver
238  //=========================
239  MA42ID(Icntl, cntl, Isave);
240 
241 
242  // Loop over the elements to setup variables associated with elements
243  //==================================================================
244  for (unsigned long e = 0; e < n_el; e++)
245  {
246  // Pointer to the element
247  GeneralisedElement* elem_pt = problem_pt->mesh_pt()->element_pt(e);
248 
249  // MH: changed array to allocateable
250  int* ivar;
251 
252  // Get number of variables in element
253  int nvar = assembly_handler_pt->ndof(elem_pt);
254 
255 
256  // Multiple equations
257  //-------------------
258  if (nvar != 1)
259  {
260  // Copy global equation numbers into local array
261  ivar = new int[nvar];
262 
263  for (int i = 0; i < nvar; i++)
264  {
265  // Need to add one to equation numbers
266  ivar[i] = 1 + assembly_handler_pt->eqn_number(elem_pt, i);
267  }
268  }
269 
270  // Just one equation
271  //------------------
272  else
273  {
274  // Copy global equation numbers into local array - minimum length: 2
275  ivar = new int[2];
276 
277  // Here's the number of the only equation
278  int only_eqn = assembly_handler_pt->eqn_number(elem_pt, 0);
279 
280  // Need to add one to equation numbers
281  ivar[0] = 1 + only_eqn;
282 
283  // Now add a dummy eqn either before or after the current one
284  int dummy_eqn;
285  if (only_eqn != (n_dof - 1))
286  {
287  dummy_eqn = only_eqn + 1;
288  }
289  else
290  {
291  dummy_eqn = only_eqn - 1;
292  }
293  ivar[1] = 1 + dummy_eqn;
294 
295  nvar = 2;
296  }
297 
298 
299  // Now call the frontal routine
300  // GB: added check to exclude case with no dofs
301  if (nvar)
302  {
303  MA42AD(nvar, ivar, ndf, last, n_dof, Icntl, Isave, Info);
304  // ALH : throw an exception if the frontal_solver fails
305  if (Info[0] < 0)
306  {
307  throw NewtonSolverError(true);
308  }
309  }
310 
311  // Cleanup
312  delete[] ivar;
313  ivar = 0;
314  }
315 
316 
317  // Loop over the elements again for symbolic factorisation
318  //=======================================================
319  for (unsigned long e = 0; e < n_el; e++)
320  {
321  // Pointer to the element
322  GeneralisedElement* elem_pt = problem_pt->mesh_pt()->element_pt(e);
323 
324  // MH: changed array to allocateable
325  int* ivar;
326 
327  // Get number of variables in element
328  int nvar = assembly_handler_pt->ndof(elem_pt);
329 
330  // Multiple equations
331  //-------------------
332  if (nvar != 1)
333  {
334  // Copy global equation numbers into local array
335  ivar = new int[nvar];
336 
337  for (int i = 0; i < nvar; i++)
338  {
339  // Need to add one to equation numbers
340  ivar[i] = 1 + assembly_handler_pt->eqn_number(elem_pt, i);
341  }
342  }
343 
344  // Just one equation
345  //------------------
346  else
347  {
348  // Copy global equation numbers into local array - minimum length: 2
349  ivar = new int[2];
350 
351  // Here's the number of the only equation
352  int only_eqn = assembly_handler_pt->eqn_number(elem_pt, 0);
353 
354  // Need to add one to equation numbers
355  ivar[0] = 1 + only_eqn;
356 
357  // Now add a dummy eqn either before or after the current one
358  int dummy_eqn;
359  if (only_eqn != (n_dof - 1))
360  {
361  dummy_eqn = only_eqn + 1;
362  }
363  else
364  {
365  dummy_eqn = only_eqn - 1;
366  }
367  ivar[1] = 1 + dummy_eqn;
368 
369  nvar = 2;
370  }
371 
372  // GB: added check to exclude case with no dofs
373  if (nvar)
374  {
375  MA42JD(nvar, ivar, ndf, last, nmaxe, ifsize, Icntl, Isave, Info);
376 
377  // ALH : throw an exception if the frontal_solver fails
378  if (Info[0] < 0)
379  {
380  throw NewtonSolverError(true);
381  }
382  }
383 
384  // Cleanup
385  delete[] ivar;
386  ivar = 0;
387 
388  } // end of symbolic factorisation
389 
390 
391  // Front sizes: "Somewhat larger than..."
392  //---------------------------------------
393  front0_recommendation = ifsize[0];
394  front1_recommendation = ifsize[1];
395  if (!exact_nfront_available)
396  {
397  nfront[0] = int(ceil(Front_factor * double(front0_recommendation)));
398  nfront[1] = int(ceil(Front_factor * double(front1_recommendation)));
399 
400  if (n_dof < nfront[0]) nfront[0] = n_dof;
401  if (n_dof < nfront[1]) nfront[1] = n_dof;
402  }
403  // We have a problem if the front size is cocked
404 
405 
406  // Sizes for lenbuf[]: "Somewhat larger than..."
407  //----------------------------------------------
408  lenbuf0_recommendation = ifsize[2] + ndf;
409  // If we are storing the matrix,
410  // we need to allocate storage for lenbuf_1
411  if (Enable_resolve)
412  {
413  lenbuf1_recommendation = ifsize[3];
414  }
415  // Otherwise set it to zero
416  else
417  {
418  lenbuf1_recommendation = 0;
419  }
420  lenbuf2_recommendation = ifsize[4];
421 
422 
423  // Enable use of direct access files?
424  //----------------------------------
426  {
427  if (Doc_stats)
428  {
429  oomph_info << "Using direct access files" << std::endl;
430  }
431 
432  // Unit numbers for direct access files (middle one only used for
433  // re-solve; set to zero as this is not used here).
434  int istrm[3];
435  istrm[0] = 17;
436  // If we are storing the matrix, set the stream
437  if (Enable_resolve)
438  {
439  istrm[1] = 19;
440  }
441  // otherwise, set it to zero
442  else
443  {
444  istrm[1] = 0;
445  }
446  istrm[2] = 18;
447 
448  // Set up the memory: Need memory "somewhat larger" than ...
449  double factor = 1.1;
450  lenbuf[0] = int(ceil(factor * double(10 * (nfront[0] + 1))));
451  // If we are storing the matrix, set the value
452  if (Enable_resolve)
453  {
454  lenbuf[1] = int(ceil(factor * double(10 * (nfront[0]))));
455  }
456  // Otherwise, set to zero
457  else
458  {
459  lenbuf[1] = 0;
460  }
461  lenbuf[2] = int(ceil(factor * double(10 * (2 * nfront[0] + 5))));
462 
463 
464  // Initial size allocation: Need memory "somewhat larger" than ...
465  if (exact_lenfle_available)
466  {
467  lenfle[0] = exact_lenfle[0];
468  lenfle[1] = exact_lenfle[1];
469  lenfle[2] = exact_lenfle[2];
470  }
471  else
472  {
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)));
479  }
480 
481  // Setup direct access files
482  MA42PD(istrm, lenbuf, lenfle, Icntl, Isave, Info);
483  }
484  else
485  {
486  if (Doc_stats)
487  {
488  oomph_info << "Not using direct access files" << std::endl;
489  }
490 
491  // Initial size allocation: Need memory "somewhat larger" than ...
492  if (exact_lenbuf_available)
493  {
494  lenbuf[0] = exact_lenbuf[0];
495  lenbuf[1] = exact_lenbuf[1];
496  lenbuf[2] = exact_lenbuf[2];
497  }
498  else
499  {
500  lenbuf[0] =
501  int(ceil(Lenbuf_factor0 * double(lenbuf0_recommendation)));
502  // If we are storing the matrix, set the buffer size
503  if (Enable_resolve)
504  {
505  lenbuf[1] =
506  int(ceil(Lenbuf_factor1 * double(lenbuf1_recommendation)));
507  }
508  // Otherwise its zero
509  else
510  {
511  lenbuf[1] = 0;
512  }
513  lenbuf[2] =
514  int(ceil(Lenbuf_factor2 * double(lenbuf2_recommendation)));
515  }
516  }
517 
518 
519  if (Doc_stats)
520  {
521  oomph_info << "\n FRONT SIZE (min and actual): " << ifsize[0] << " "
522  << nfront[0] << std::endl;
523  }
524 
525 
526  // Initialise success
527  bool success = true;
528 
529  // Workspace arrays: calculate amount in local variables initiall
530  int lw = 1 + lenbuf[0] + lenbuf[1] + nfront[0] * nfront[1];
531  if (lrhs * nfront[0] > nrhs * nfront[1])
532  {
533  lw += lrhs * nfront[0];
534  }
535  else
536  {
537  lw += nrhs * nfront[1];
538  }
539 
540  int liw = lenbuf[2] + 2 * nfront[0] + 4 * nfront[1];
541 
542  // Set up memory for w and iw
543  // Again allocate dynamically from the heap, rather than the stack
544  // If the required amount of storage has changed, reallocate
545  // and store the values in the object member data
546  if (lw != Lw)
547  {
548  // Set the new value of Lw (member data)
549  Lw = lw;
550  // Delete the previously allocated storage
551  if (W) delete[] W;
552  // Now allocate new storage
553  W = new (std::nothrow) double[Lw];
554  if (!W)
555  {
556  throw OomphLibError("Out of memory in allocation of w\n",
559  }
560  }
561 
562  // If the required amount of storage has changed, reallocate
563  if (liw != Liw)
564  {
565  // Set the new value of Liw (member data)
566  Liw = liw;
567  // Delete the previously allocated storgae
568  if (IW != 0)
569  {
570  delete[] IW;
571  }
572  // Now allocate new storage
573  IW = new (std::nothrow) int[Liw];
574  if (!IW)
575  {
576  throw OomphLibError("Out of memory in allocation of iw\n",
579  }
580  }
581 
582  // Doc
583  if (Doc_stats)
584  {
585  double temp = (lenbuf[0] * sizeof(double) + lenbuf[2] * sizeof(int)) /
586  (1024.0 * 1024.0);
587  oomph_info << "\n ESTIMATED MEMORY USAGE " << temp << "Mb" << std::endl;
588  }
589 
590 
591  // Now do the actual frontal assembly and solve loop
592  //=================================================
593  for (unsigned long e = 0; e < n_el; e++)
594  {
595  // Get pointer to the element
596  GeneralisedElement* elem_pt = problem_pt->mesh_pt()->element_pt(e);
597 
598  // Get number of variables in element
599  int nvar = assembly_handler_pt->ndof(elem_pt);
600 
601  // MH: changed array to allocatable
602  int* ivar;
603 
604  // Multiple equations
605  //-------------------
606  if (nvar != 1)
607  {
608  // Copy global equation numbers into local array
609  ivar = new int[nvar];
610 
611  for (int i = 0; i < nvar; i++)
612  {
613  // Need to add one to equation numbers
614  ivar[i] = 1 + assembly_handler_pt->eqn_number(elem_pt, i);
615  }
616  nmaxe = nvar;
617  }
618 
619  // Just one equation
620  //------------------
621  else
622  {
623  // Copy global equation numbers into local array - minimum length: 2
624  ivar = new int[2];
625 
626  // Here's the number of the only equation
627  int only_eqn = assembly_handler_pt->eqn_number(elem_pt, 0);
628 
629  // Need to add one to equation numbers
630  ivar[0] = 1 + only_eqn;
631 
632  // Now add a dummy eqn either before or after the current one
633  int dummy_eqn;
634  if (only_eqn != (n_dof - 1))
635  {
636  dummy_eqn = only_eqn + 1;
637  }
638  else
639  {
640  dummy_eqn = only_eqn - 1;
641  }
642  ivar[1] = 1 + dummy_eqn;
643 
644  nmaxe = 2;
645  }
646 
647  // Set up matrices and Vector for call to get_residuals
648  Vector<double> residuals(nvar);
649  DenseMatrix<double> jacobian(nvar);
650 
651  // Get the residuals and jacobian
652  assembly_handler_pt->get_jacobian(elem_pt, residuals, jacobian);
653 
654  // Add dummy rows and columns if required
655  if (nvar == 1)
656  {
657  double onlyjac = jacobian(0, 0);
658  jacobian.resize(2, 2);
659  jacobian(0, 0) = onlyjac;
660  jacobian(1, 0) = 0.0;
661  jacobian(0, 1) = 0.0;
662  jacobian(1, 1) = 0.0;
663 
664  double onlyres = residuals[0];
665  residuals.resize(2);
666  residuals[0] = onlyres;
667  residuals[1] = 0.0;
668 
669  nvar = 2;
670  }
671 
672 
673  // GB: added check to exclude case with no dofs
674  if (nvar)
675  {
676  // Now translate the residuals and jacobian into form to be
677  // taken by stupid FORTRAN frontal solver
678  // double avar[nvar][nmaxe], rhs[1][nmaxe];
679  // Assign memory on the heap rather than the stack because the ndofs
680  // could get too large
681  double** avar = new double*[nvar];
682  double* tmp = new double[nvar * nmaxe];
683  for (int i = 0; i < nvar; i++)
684  {
685  avar[i] = &tmp[i * nmaxe];
686  }
687  double** rhs = new double*[1];
688  rhs[0] = new double[nmaxe];
689 
690 
691  for (int i = 0; i < nmaxe; i++)
692  {
693  rhs[0][i] = residuals[i];
694  for (int j = 0; j < nvar; j++)
695  {
696  // Note need to transpose here
697  avar[j][i] = jacobian(i, j);
698  }
699  }
700 
701  // Call the frontal solver
702  MA42BD(nvar,
703  ivar,
704  ndf,
705  last,
706  nmaxe,
707  avar,
708  nrhs,
709  rhs,
710  lrhs,
711  n_dof,
712  dx,
713  nfront,
714  lenbuf,
715  Lw,
716  W,
717  Liw,
718  IW,
719  Icntl,
720  cntl,
721  Isave,
722  Info,
723  rinfo);
724 
725 
726  // Error check:
727  if (Info[0] < 0)
728  {
729  if (Doc_stats)
730  oomph_info << "Error: Info[0]=" << Info[0] << std::endl;
731 
732  // Solve isn't going to be successful
733  success = false;
734 
735  // Error: Entries in lenbuf too small -- this is covered
736  if (Info[0] == -16)
737  {
738  if (Doc_stats)
739  oomph_info << "lenbuf[] too small -- can recover..."
740  << std::endl;
741  }
742  else if (Info[0] == -12)
743  {
744  if (Doc_stats)
745  oomph_info << "nfront[] too small -- can recover..."
746  << std::endl;
747  }
748  else if (Info[0] == -17)
749  {
750  if (Doc_stats)
751  oomph_info << "lenfle[] too small -- can recover..."
752  << std::endl;
753  }
754  else
755  {
756  if (Doc_stats)
757  {
758  oomph_info << "Can't recover from this error" << std::endl;
759  }
760  throw NewtonSolverError(true);
761  }
762  }
763 
764  // Clean up the memory
765  delete[] rhs[0];
766  rhs[0] = 0;
767  delete[] rhs;
768  rhs = 0;
769  delete[] avar[0];
770  avar[0] = 0;
771  delete[] avar;
772  }
773 
774  // Cleanup
775  delete[] ivar;
776  ivar = 0;
777 
778  } // end of loop over elements for assemble/solve
779 
780  // Set the sign of the jacobian matrix
781  problem_pt->sign_of_jacobian() = Info[1];
782 
783  // If we are not storing the matrix, then delete the assigned workspace
784  if (!Enable_resolve)
785  {
786  // Free the workspace memory assigned and set stored values to zero
787  delete[] IW;
788  IW = 0;
789  Liw = 0;
790  delete[] W;
791  W = 0;
792  Lw = 0;
793  // Reset the number of dofs
794  N_dof = 0;
795  }
796 
797  // We've done the elements -- did we encounter an error
798  // that forces us to re-allocate workspace?
799  if (success)
800  {
801  // We're done!
802  not_done = false;
803  }
804  else
805  {
806  // Reset sizes for lenbuf
808  {
809  exact_lenbuf[0] = Info[4];
810  exact_lenbuf[1] = Info[5];
811  exact_lenbuf[2] = Info[6];
812  exact_lenbuf_available = true;
813  }
814 
815  // nfront[] has already been overwritten with required values -- don't
816  // need to update anything. Just indicate that new values are
817  // available so they don't have to be re-assigned.
818  exact_nfront_available = true;
819 
820  // Reset sizes for lenfle
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;
825  }
826 
827  } // end of loop over shuffling of workspace array sizes until it all
828  // fits...
829 
830  result.build(&dist);
831  // Now load the values back into result
832  for (int i = 0; i < n_dof; i++) result[i] = dx[0][i];
833 
834  // Print the actual memory used
835  if (Doc_stats)
836  {
838  {
839  double temp = (Info[4] * sizeof(double) + Info[6] * sizeof(int)) /
840  (1024.0 * 1024.0);
841  oomph_info << " TOTAL MEMORY USED " << temp << "Mb" << std::endl;
842  }
843  oomph_info << std::endl;
844  oomph_info << "lenbuf[]: " << lenbuf[0] << " " << lenbuf[1] << " "
845  << lenbuf[2] << " " << std::endl;
846  oomph_info << "lenbuf[] factors required and initially specified:"
847  << std::endl;
848  oomph_info << "lenbuf[0]: " << Info[4] / double(lenbuf0_recommendation)
849  << " " << Lenbuf_factor0 << std::endl;
850  oomph_info << "lenbuf[1]: " << Info[5] / double(lenbuf1_recommendation)
851  << " " << Lenbuf_factor1 << std::endl;
852 
853  oomph_info << "lenbuf[2]: " << Info[6] / double(lenbuf2_recommendation)
854  << " " << Lenbuf_factor2 << std::endl;
855  oomph_info << "nfront[] factors required and initially specified:"
856  << std::endl;
857  oomph_info << "nfront[0]: " << nfront[0] / double(front0_recommendation)
858  << " " << Front_factor << std::endl;
859  oomph_info << "nfront[1]: " << nfront[1] / double(front1_recommendation)
860  << " " << Front_factor << std::endl;
862  {
863  oomph_info << "lenfle[]: " << lenfle[0] << " " << lenfle[1] << " "
864  << lenfle[2] << " " << std::endl;
865  oomph_info << "lenfle[] factors required and initially specified:"
866  << std::endl;
867  oomph_info << "lenfle[0]: "
868  << Info[9] * lenbuf[0] / double(lenfle0_recommendation)
869  << " " << Lenfle_factor << std::endl;
870  oomph_info << "lenfle[1]: "
871  << Info[10] * lenbuf[1] / double(lenfle1_recommendation)
872  << " " << Lenfle_factor << std::endl;
873  oomph_info << "lenfle[2]: "
874  << Info[11] * lenbuf[2] / double(lenfle2_recommendation)
875  << " " << Lenfle_factor << std::endl;
876  }
877  }
878 
879  // Free the memory assigned
880  delete[] * dx;
881  delete dx;
882  delete[] last;
883  }
void build_distribution(const LinearAlgebraDistribution *const dist_pt)
Definition: linear_algebra_distribution.h:507
void reorder_elements(Problem *const &problem_pt)
Function to reorder the elements based on Sloan's algorithm.
Definition: frontal_solver.cc:969
void solve_for_one_dof(Problem *const &problem_pt, DoubleVector &result)
Definition: frontal_solver.cc:48
bool Enable_resolve
Definition: linear_solver.h:73
#define MA42ID(ICNTL, CNTL, ISAVE)
Definition: frontal.h:28
#define MA42PD(ISTRM, LENBUF, LENFLE, ICNTL, ISAVE, INFO)
#define MA42BD(NVAR, IVAR, NDF, LAST, NMAXE, AVAR, NRHS, RHS, LRHS, LX, X, NFRONT, LENBUF, LW, W, LIW, IW, ICNTL, CNTL, ISAVE, INFO, RINFO)
Definition: frontal.h:117
#define MA42JD(NVAR, IVAR, NDF, LAST, NMAXE, IFSIZE, ICNTL, ISAVE, INFO)
#define MA42AD(NVAR, IVAR, NDF, LAST, LENLST, ICNTL, ISAVE, INFO)
Definition: frontal.h:32
static constexpr const last_t last
Definition: IndexedViewHelper.h:48
return int(ret)+1
Eigen::Matrix< Scalar, Dynamic, Dynamic, ColMajor > tmp
Definition: level3_impl.h:365
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 ceil(const bfloat16 &a)
Definition: BFloat16.h:644
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References oomph::Problem::assembly_handler_pt(), oomph::DoubleVector::build(), oomph::DistributableLinearAlgebraObject::build_distribution(), Eigen::bfloat16_impl::ceil(), oomph::Problem::communicator_pt(), Doc_stats, e(), oomph::Mesh::element_pt(), oomph::LinearSolver::Enable_resolve, oomph::AssemblyHandler::eqn_number(), Front_factor, oomph::AssemblyHandler::get_jacobian(), i, Icntl, Info, int(), Isave, IW, j, Eigen::placeholders::last, Lenbuf_factor0, Lenbuf_factor1, Lenbuf_factor2, Lenfle_factor, Liw, Lw, MA42AD, MA42BD, MA42ID, MA42JD, MA42PD, oomph::Problem::mesh_pt(), N_dof, oomph::Problem::ndof(), oomph::AssemblyHandler::ndof(), oomph::Mesh::nelement(), oomph::OomphCommunicator::nproc(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, oomph::oomph_info, reorder_elements(), Reorder_flag, oomph::DenseMatrix< T >::resize(), oomph::Problem::sign_of_jacobian(), solve_for_one_dof(), tmp, Use_direct_access_files, and W.

◆ solve_for_one_dof()

void oomph::HSL_MA42::solve_for_one_dof ( Problem *const &  problem_pt,
DoubleVector &  result 
)
private

Special solver for problems with 1 dof (MA42 can't handle this case so solve() forwards the "solve" to this function.

Special solver for problems with one DOF – HSL_MA42 can't handle that!

50  {
51  // Find the number of elements
52  unsigned long n_el = problem_pt->mesh_pt()->nelement();
53 
54 #ifdef PARANOID
55  // Find the number of dofs (variables)
56  int n_dof = problem_pt->ndof();
57  // Check
58  if (n_dof != 1)
59  {
60  throw OomphLibError(
61  "You can only call this if the problem has just one dof!",
64  }
65 #endif
66 
67  // Global jac and residuals are scalars!
68  double global_jac = 0.0;
69  double global_res = 0.0;
70 
71  // Locally cache pointer to assembly handler
72  AssemblyHandler* const assembly_handler_pt =
73  problem_pt->assembly_handler_pt();
74 
75 
76  // Do the assembly
77  for (unsigned long e = 0; e < n_el; e++)
78  {
79  // Get pointer to the element
80  GeneralisedElement* elem_pt = problem_pt->mesh_pt()->element_pt(e);
81 
82  // Get number of variables in element
83  int nvar = assembly_handler_pt->ndof(elem_pt);
84 
85  // Only assemble if there's something to be assembled
86  if (nvar > 0)
87  {
88  // Set up matrices and Vector for call to get_residuals
89  Vector<double> residuals(nvar);
90  DenseMatrix<double> jacobian(nvar);
91 
92  // Get the residuals and jacobian
93  assembly_handler_pt->get_jacobian(elem_pt, residuals, jacobian);
94 
95  // Add contribution
96  global_jac += jacobian(0, 0);
97  global_res += residuals[0];
98  }
99  }
100 
101  // "Solve"
102  result[0] = global_res / global_jac;
103 
104  // If we are storing the matrix, allocate the storage
105  if (Enable_resolve)
106  {
107  // If storage has been allocated delete it
108  if (W != 0)
109  {
110  delete[] W;
111  }
112  // Now allocate new storage
113  W = new double[1];
114  // Store the global jacobian
115  W[0] = global_jac;
116  // Set the number of degrees of freedom
117  N_dof = 1;
118  }
119  // Set the sign of the jacobian
120  problem_pt->sign_of_jacobian() =
121  static_cast<int>(std::fabs(global_jac) / global_jac);
122  }
Real fabs(const Real &a)
Definition: boostmultiprec.cpp:117

References oomph::Problem::assembly_handler_pt(), e(), oomph::Mesh::element_pt(), oomph::LinearSolver::Enable_resolve, boost::multiprecision::fabs(), oomph::AssemblyHandler::get_jacobian(), oomph::Problem::mesh_pt(), N_dof, oomph::Problem::ndof(), oomph::AssemblyHandler::ndof(), oomph::Mesh::nelement(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, oomph::Problem::sign_of_jacobian(), and W.

Referenced by solve().

Member Data Documentation

◆ Doc_stats

bool oomph::HSL_MA42::Doc_stats
private

Doc the solver stats or stay quiet?

Referenced by disable_doc_stats(), enable_doc_stats(), HSL_MA42(), reorder_elements(), and solve().

◆ Front_factor

double oomph::HSL_MA42::Front_factor
private

Factor to increase storage for front size; see MA42 documentation for details.

Referenced by front_factor(), HSL_MA42(), and solve().

◆ Icntl

int oomph::HSL_MA42::Icntl[8]
private

Control flag for MA42; see MA42 documentation for details.

Referenced by resolve(), and solve().

◆ Info

int oomph::HSL_MA42::Info[23]
private

Control flag for MA42; see MA42 documentation for details.

Referenced by resolve(), and solve().

◆ Isave

int oomph::HSL_MA42::Isave[45]
private

Control flag for MA42; see MA42 documentation for details.

Referenced by resolve(), and solve().

◆ IW

int* oomph::HSL_MA42::IW
private

Integer workspace storage for MA42.

Referenced by clean_up_memory(), resolve(), and solve().

◆ Lenbuf_factor0

double oomph::HSL_MA42::Lenbuf_factor0
private

Factor to increase storage for lenbuf[0]; see MA42 documentation for details.

Referenced by HSL_MA42(), lenbuf_factor0(), and solve().

◆ Lenbuf_factor1

double oomph::HSL_MA42::Lenbuf_factor1
private

Factor to increase storage for lenbuf[1]; see MA42 documentation for details

Referenced by HSL_MA42(), lenbuf_factor1(), and solve().

◆ Lenbuf_factor2

double oomph::HSL_MA42::Lenbuf_factor2
private

Factor to increase storage for lenbuf[2]; see MA42 documentation for details.

Referenced by HSL_MA42(), lenbuf_factor2(), and solve().

◆ Lenfle_factor

double oomph::HSL_MA42::Lenfle_factor
private

Factor to increase size of direct access files; see MA42 documentation for details.

Referenced by HSL_MA42(), lenfle_factor(), and solve().

◆ Liw

int oomph::HSL_MA42::Liw
private

Size of the integer workspace array.

Referenced by clean_up_memory(), resolve(), and solve().

◆ Lw

int oomph::HSL_MA42::Lw
private

Size of the workspace array, W.

Referenced by clean_up_memory(), resolve(), and solve().

◆ N_dof

unsigned long oomph::HSL_MA42::N_dof
private

Size of the linear system.

Referenced by resolve(), solve(), and solve_for_one_dof().

◆ Reorder_flag

bool oomph::HSL_MA42::Reorder_flag
private

Reorder elements with Sloan's algorithm?

Referenced by disable_reordering(), enable_reordering(), HSL_MA42(), and solve().

◆ Use_direct_access_files

bool oomph::HSL_MA42::Use_direct_access_files
private

Use direct access files?

Referenced by disable_direct_access_files(), enable_direct_access_files(), HSL_MA42(), and solve().

◆ W

double* oomph::HSL_MA42::W
private

Workspace storage for MA42.

Referenced by clean_up_memory(), resolve(), solve(), and solve_for_one_dof().


The documentation for this class was generated from the following files: