MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
optcontactproblem.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#include "optcontactproblem.hpp"
13
14namespace mfem
15{
16
17void OptContactProblem::ReleaseMemory()
18{
19 delete J; J = nullptr;
20 delete Jt; Jt = nullptr;
21 delete Pc; Pc = nullptr;
22 delete NegId; NegId = nullptr;
23 delete Iu; Iu = nullptr;
24 delete negIu; negIu = nullptr;
25 delete Mv; Mv = nullptr;
26 delete Mcs; Mcs = nullptr;
27 if (dcdu)
28 {
29 delete dcdu;
30 dcdu = nullptr;
31 }
32}
33
34void OptContactProblem::ComputeGapJacobian()
35{
36 if (J) { delete J; }
37 J = const_cast<HypreParMatrix *>(SetupTribol(problem->GetMesh(),coords,
38 problem->GetEssentialDofs(),
39 mortar_attrs, nonmortar_attrs,gapv, tribol_ratio));
40
41 dof_starts.SetSize(2);
42 dof_starts[0] = J->ColPart()[0];
43 dof_starts[1] = J->ColPart()[1];
44
45 constraints_starts.SetSize(2);
46 if (bound_constraints_activated)
47 {
48 constraints_starts[0] = J->RowPart()[0] + 2 * J->ColPart()[0];
49 constraints_starts[1] = J->RowPart()[1] + 2 * J->ColPart()[1];
50 }
51 else
52 {
53 constraints_starts[0] = J->RowPart()[0];
54 constraints_starts[1] = J->RowPart()[1];
55 }
56}
57
59 const std::set<int> & mortar_attrs_,
60 const std::set<int> & nonmortar_attrs_,
61 real_t tribol_ratio_,
62 bool bound_constraints_)
63 : problem(problem_), mortar_attrs(mortar_attrs_),
64 nonmortar_attrs(nonmortar_attrs_),
65 tribol_ratio(tribol_ratio_),
66 bound_constraints(bound_constraints_)
67{
68 comm = problem->GetComm();
69 vfes = problem->GetFESpace();
70 block_offsetsg.SetSize(4);
71}
72
74 const Vector & xref_)
75{
76 ReleaseMemory();
77
78 coords = coords_;
79 xref.SetDataAndSize(xref_.GetData(), xref_.Size());
80
81 ComputeGapJacobian();
82
83 problem->Getxrefbc(xrefbc);
84 const Array<int> & ess_tdof_list = problem->GetEssentialDofs();
85 Vector ess_values;
86
87 xrefbc.GetSubVector(ess_tdof_list, ess_values);
88 xrefbc=xref;
89 xrefbc.SetSubVector(ess_tdof_list, ess_values);
90
91 if (problem->IsNonlinear())
92 {
93 energy_ref = problem->GetEnergy(xrefbc);
94 problem->GetGradient(xrefbc,grad_ref);
95 Kref = problem->GetHessian(xrefbc);
96 }
97 dimU = J->Width();
98 dimG = J->Height();
99 num_constraints = J->GetGlobalNumRows();
100
101 block_offsetsg[0] = 0;
102 block_offsetsg[1] = dimG;
103 block_offsetsg[2] = dimU;
104 block_offsetsg[3] = dimU;
105 block_offsetsg.PartialSum();
106
107 Vector diagVec(dimU); diagVec = 0.0;
108 SparseMatrix * tempSparse;
109
110 diagVec = 1.0;
111 tempSparse = new SparseMatrix(diagVec);
112 Iu = new HypreParMatrix(comm, GetGlobalNumDofs(), GetDofStarts(), tempSparse);
113 HypreStealOwnership(*Iu, *tempSparse);
114 delete tempSparse;
115
116 diagVec = -1.0;
117 tempSparse = new SparseMatrix(diagVec);
118 negIu = new HypreParMatrix(comm, GetGlobalNumDofs(), GetDofStarts(),
119 tempSparse);
120 HypreStealOwnership(*negIu, *tempSparse);
121 delete tempSparse;
122
123 dimM = dimG;
124 dimC = dimM;
125
126 ParBilinearForm MassForm(vfes);
128 MassForm.Assemble();
129
130 Array<int> empty_tdof_list;
131 Mv = new HypreParMatrix();
132 MassForm.FormSystemMatrix(empty_tdof_list,*Mv);
133
134 Vector onev(Mv->Width()); onev = 1.0;
135 Mvlump.SetSize(Mv->Height());
136 Mv->Mult(onev, Mvlump);
137
138 if (!dl.Size())
139 {
140 dl.SetSize(dimU); dl = 0.0;
141 if (bound_constraints)
142 {
143 eps.SetSize(dimU); eps = 0.0; // minimum size of eps controlled by eps_min
144 }
145 }
146}
147
149{
150 if (bound_constraints_activated)
151 {
152 Array2D<const HypreParMatrix *> dcduBlockMatrix(3, 1);
153 dcduBlockMatrix(0, 0) = J;
154 dcduBlockMatrix(1, 0) = Iu;
155 dcduBlockMatrix(2, 0) = negIu;
156 if (dcdu) { delete dcdu; }
157 dcdu = HypreParMatrixFromBlocks(dcduBlockMatrix);
158 return dcdu;
159 }
160 else
161 {
162 return J;
163 }
164}
165
167{
168 if (!NegId)
169 {
170 Vector negone(dimM); negone = -1.0;
171 SparseMatrix diag(negone);
172 NegId = new HypreParMatrix(comm, GetGlobalNumConstraints(),
173 GetConstraintsStarts(), &diag);
174 HypreStealOwnership(*NegId, diag);
175 }
176 return NegId;
177}
178
180{
181 if (!Pc)
182 {
183 if (!Jt)
184 {
185 Jt = J->Transpose();
186 Jt->EliminateRows(problem->GetEssentialDofs());
187 }
188 int hJt = Jt->Height();
189 SparseMatrix mergedJt;
190 Jt->MergeDiagAndOffd(mergedJt);
191 Array<int> nonzerorows;
192 for (int i = 0; i<hJt; i++)
193 {
194 if (!mergedJt.RowIsEmpty(i))
195 {
196 nonzerorows.Append(i);
197 }
198 }
199 int nrows_c = nonzerorows.Size();
200 SparseMatrix Pct(nrows_c,vfes->GlobalTrueVSize());
201
202 for (int i = 0; i<nrows_c; i++)
203 {
204 int col = nonzerorows[i]+vfes->GetMyTDofOffset();
205 Pct.Set(i,col,1.0);
206 }
207 Pct.Finalize();
208
209 HYPRE_BigInt rows_c[2];
210
211 HYPRE_BigInt row_offset_c;
212 HYPRE_BigInt nrows_c_bigint = nrows_c;
213 MPI_Scan(&nrows_c_bigint,&row_offset_c,1,MPITypeMap<HYPRE_BigInt>::mpi_type,
214 MPI_SUM,comm);
215
216 row_offset_c-=nrows_c_bigint;
217 rows_c[0] = row_offset_c;
218 rows_c[1] = row_offset_c+nrows_c;
219
220 HYPRE_BigInt glob_nrows_c;
221 HYPRE_BigInt glob_ncols_c = vfes->GlobalTrueVSize();
222 MPI_Allreduce(&nrows_c_bigint, &glob_nrows_c,1,
224 MPI_SUM,comm);
225
226 HYPRE_BigInt * J;
227#ifndef HYPRE_BIGINT
228 J = Pct.GetJ();
229#else
230 J = new HYPRE_BigInt[Pct.NumNonZeroElems()];
231 for (int i = 0; i < Pct.NumNonZeroElems(); i++)
232 {
233 J[i] = Pct.GetJ()[i];
234 }
235#endif
236 HypreParMatrix * P_ct = new HypreParMatrix(comm, nrows_c, glob_nrows_c,
237 glob_ncols_c, Pct.GetI(), J,
238 Pct.GetData(), rows_c,vfes->GetTrueDofOffsets());
239 Pc = P_ct->Transpose();
240 delete P_ct;
241#ifdef HYPRE_BIGINT
242 delete [] J;
243#endif
244 }
245 return Pc;
246}
247
248void OptContactProblem::g(const Vector & d, Vector & gd)
249{
250 Vector temp(dimU); temp = 0.0;
251 temp.Set(1.0, d);
252 temp.Add(-1.0, xref);
253 J->Mult(temp, gd);
254 gd.Add(1.0, gapv);
255}
256
257// [ g1(d) ]
258// c(d, s) = [ eps + (d - dl) ] - s
259// [ eps - (d - dl) ]
261{
262 const Vector disp = x.GetBlock(0);
263 const Vector slack = x.GetBlock(1);
264
265 if (bound_constraints_activated)
266 {
267 BlockVector yblock(block_offsetsg); yblock = 0.0;
268
269 g(disp, yblock.GetBlock(0));
270 yblock.GetBlock(1).Set( 1.0, disp );
271 yblock.GetBlock(1).Add(-1.0, dl);
272 yblock.GetBlock(2).Set(-1.0, yblock.GetBlock(1));
273 yblock.GetBlock(1).Add(1.0, eps);
274 yblock.GetBlock(2).Add(1.0, eps);
275 y.Set(1.0, yblock);
276 y.Add(-1.0, slack);
277 }
278 else
279 {
280 g(disp, y);
281 y.Add(-1., slack);
282 }
283}
284
286{
287 return E(x.GetBlock(0), eval_err);
288}
289
291 BlockVector & y)
292{
293 DdE(x.GetBlock(0), y.GetBlock(0));
294 y.GetBlock(1) = 0.0;
295}
296
297real_t OptContactProblem::E(const Vector & d, int & eval_err)
298{
299 if (problem->IsNonlinear())
300 {
301 // (d - xref)^T [ 1/2 K * (d - xref) + gradEQP] + EQP
302 real_t energy = 0.0;
303 Vector dx(dimU); dx = 0.0;
304 Vector temp(dimU); temp = 0.0;
305 dx.Set(1.0, d);
306 dx.Add(-1.0, xrefbc);
307 Kref->Mult(dx, temp);
308 temp *= 0.5;
309 temp.Add(1.0, grad_ref);
310 energy = InnerProduct(comm, dx, temp);
311 energy += energy_ref;
312 eval_err = 0;
313 return energy;
314 }
315 else
316 {
317 real_t energy = problem->GetEnergy(d);
318 if (IsFinite(energy))
319 {
320 eval_err = 0;
321 }
322 else
323 {
324 eval_err = 1;
325 }
326 if (Mpi::Root() && eval_err == 1)
327 {
328 mfem::out << "energy = " << energy << std::endl;
329 mfem::out << "eval_err = " << eval_err << std::endl;
330 }
331 return energy;
332 }
333}
334
335void OptContactProblem::DdE(const Vector & d, Vector & gradE)
336{
337 if (problem->IsNonlinear())
338 {
339 // KQP * (d - xref) + gradEQP
340 Vector dx(dimU); dx = 0.0;
341 dx.Set(1.0, d);
342 dx.Add(-1.0, xrefbc);
343 Kref->Mult(dx, gradE);
344 gradE.Add(1.0, grad_ref);
345 }
346 else
347 {
348 return problem->GetGradient(d, gradE);
349 }
350}
351
353{
354 return (problem->IsNonlinear()) ? Kref : problem->GetHessian(d);
355}
356
358 bool activate_constraints)
359{
360 if (activate_constraints)
361 {
362 eps_min = std::max(eps_min, GlobalLpNorm(infinity(), eps.Normlinf(), comm));
363 for (int j = 0; j < dimU; j++)
364 {
365 eps(j) = std::max(eps_min, eps(j));
366 }
367 }
368 else
369 {
370 for (int j = 0; j < dimU; j++)
371 {
372 eps(j) = std::max(eps(j), std::abs(dx(j)));
373 }
374 }
375}
376
378{
379 dl.Set(1.0, xrefbc);
380 bound_constraints_activated = true;
381 constraints_starts[0] = J->RowPart()[0] + 2 * J->ColPart()[0];
382 constraints_starts[1] = J->RowPart()[1] + 2 * J->ColPart()[1];
383 num_constraints = J->GetGlobalNumRows() + 2 * J->GetGlobalNumCols();
384 dimM = dimG + 2 * dimU;
385 dimC = dimM;
386}
387
389 ParGridFunction * coords,
390 const Array<int> & ess_tdofs, const std::set<int> & mortar_attrs,
391 const std::set<int> & non_mortar_attrs,
392 Vector &gap, real_t ratio)
393{
394 axom::slic::SimpleLogger logger;
395 axom::slic::setIsRoot(mfem::Mpi::Root());
396
397 int coupling_scheme_id = 0;
398 int mesh1_id = 0; int mesh2_id = 1;
399
400 tribol::registerMfemCouplingScheme(
401 coupling_scheme_id, mesh1_id, mesh2_id,
402 *pmesh, *coords, mortar_attrs, non_mortar_attrs,
403 tribol::SURFACE_TO_SURFACE,
404 tribol::NO_SLIDING,
405 tribol::SINGLE_MORTAR,
406 tribol::FRICTIONLESS,
407 tribol::LAGRANGE_MULTIPLIER,
408 tribol::BINNING_GRID
409 );
410
411 tribol::setBinningProximityScale(coupling_scheme_id, ratio);
412
413 // Access Tribol's pressure grid function (on the contact surface)
414 auto& pressure = tribol::getMfemPressure(coupling_scheme_id);
415
416 ParBilinearForm acs_form(pressure.ParFESpace());
418 acs_form.Assemble();
419 Array<int> empty_tdof_list;
420 Mcs = new HypreParMatrix();
421 acs_form.FormSystemMatrix(empty_tdof_list,*Mcs);
422
423 Vector onecs(Mcs->Width()); onecs = 1.0;
424 Mcslumpfull.SetSize(Mcs->Height()); //Vector
425 Mcs->Mult(onecs, Mcslumpfull);
426
427 // Set Tribol options for Lagrange multiplier enforcement
428 tribol::setLagrangeMultiplierOptions(
429 coupling_scheme_id,
430 tribol::ImplicitEvalMode::MORTAR_RESIDUAL_JACOBIAN
431 );
432
433 // Update contact mesh decomposition
434 tribol::updateMfemParallelDecomposition();
435
436 // Update contact gaps, forces, and tangent stiffness
437 int cycle = 1; // pseudo cycle
438 real_t t = 1.0; // pseudo time
439 real_t dt = 1.0; // pseudo dt
440 tribol::update(cycle, t, dt);
441
442 // Return contact contribution to the tangent stiffness matrix
443 auto A_blk = tribol::getMfemBlockJacobian(coupling_scheme_id);
444
445 HypreParMatrix * Mfull = (HypreParMatrix *)(&A_blk->GetBlock(1,0));
446 Mfull->InvScaleRows(Mcslumpfull); // scaling
447 HypreParMatrix * Me = Mfull->EliminateCols(ess_tdofs);
448 delete Me;
449
450 int h = Mfull->Height();
451 SparseMatrix merged;
452 Mfull->MergeDiagAndOffd(merged);
453 Array<int> nonzero_rows;
454
455 real_t max_l1_row_norm = 0.0;
456 real_t rel_row_norm_threshold = 1.e-5;
457 for (int i = 0; i < h; i++)
458 {
459 if (!merged.RowIsEmpty(i))
460 {
461 max_l1_row_norm = std::max( max_l1_row_norm, merged.GetRowNorml1(i));
462 }
463 }
464
465 for (int i = 0; i<h; i++)
466 {
467 if (!merged.RowIsEmpty(i))
468 {
469 if (merged.GetRowNorml1(i) > rel_row_norm_threshold * max_l1_row_norm)
470 {
471 nonzero_rows.Append(i);
472 }
473 }
474 }
475
476 int hnew = nonzero_rows.Size();
477 SparseMatrix P(hnew,h);
478
479 for (int i = 0; i<hnew; i++)
480 {
481 int col = nonzero_rows[i];
482 P.Set(i,col,1.0);
483 }
484 P.Finalize();
485
486 SparseMatrix * reduced_merged = Mult(P,merged);
487
488 HYPRE_BigInt rows[2];
489 int nrows = reduced_merged->Height();
490 HYPRE_BigInt nrows_bigint = nrows;
491 HYPRE_BigInt row_offset;
492 MPI_Scan(&nrows_bigint,&row_offset,1,MPITypeMap<HYPRE_BigInt>::mpi_type,
493 MPI_SUM,Mfull->GetComm());
494
495 row_offset-=nrows;
496 rows[0] = row_offset;
497 rows[1] = row_offset+nrows;
498 HYPRE_BigInt glob_nrows;
499 MPI_Allreduce(&nrows_bigint, &glob_nrows,1,MPITypeMap<HYPRE_BigInt>::mpi_type,
500 MPI_SUM,Mfull->GetComm());
501
502 HYPRE_BigInt glob_ncols = reduced_merged->Width();
503
504 HYPRE_BigInt * J;
505#ifndef HYPRE_BIGINT
506 J = reduced_merged->GetJ();
507#else
508 J = new HYPRE_BigInt[reduced_merged->NumNonZeroElems()];
509 for (int i = 0; i < reduced_merged->NumNonZeroElems(); i++)
510 {
511 J[i] = reduced_merged->GetJ()[i];
512 }
513#endif
514
515 HypreParMatrix * M = new HypreParMatrix(Mfull->GetComm(), nrows, glob_nrows,
516 glob_ncols, reduced_merged->GetI(), J,
517 reduced_merged->GetData(), rows, Mfull->ColPart());
518 delete reduced_merged;
519
520#ifdef HYPRE_BIGINT
521 delete [] J;
522#endif
523
524 Vector gap_full;
525 tribol::getMfemGap(coupling_scheme_id, gap_full);
526
527 auto& P_submesh = *pressure.ParFESpace()->GetProlongationMatrix();
528 Vector gap_true(P_submesh.Width());
529
530 P_submesh.MultTranspose(gap_full,gap_true);
531 gap.SetSize(nrows);
532 Mcslump.SetSize(nrows);
533
534 for (int i = 0; i<nrows; i++)
535 {
536 gap[i] = gap_true[nonzero_rows[i]];
537 Mcslump(i) = Mcslumpfull(nonzero_rows[i]);
538 }
539 gap /= Mcslump;
540 tribol::finalize();
541 return M;
542}
543
544}
Dynamic 2D array using row-major layout.
Definition array.hpp:430
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:840
int Size() const
Return the logical size of the array.
Definition array.hpp:166
void PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
Definition array.cpp:104
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:912
void AddDomainIntegrator(BilinearFormIntegrator *bfi)
Adds new Domain Integrator. Assumes ownership of bfi.
A class to handle Vectors in a block fashion.
Vector & GetBlock(int i)
Get the i-th vector in the block.
Parallel finite element operator for linear and nonlinear elasticity.
ParMesh * GetMesh() const
ParFiniteElementSpace * GetFESpace() const
const Array< int > & GetEssentialDofs() const
bool IsNonlinear()
Check if the operator is nonlinear.
void GetGradient(const Vector &u, Vector &gradE) const
Compute the gradient of the energy functional at a given displacement vector.
HypreParMatrix * GetHessian(const Vector &u)
Get the Hessian (stiffness matrix) at a given displacement vector.
void Getxrefbc(Vector &xrefbc) const
Get the displacement with essential boundary conditions applied.
real_t GetEnergy(const Vector &u) const
Compute the elastic energy functional at a given displacement vector.
Wrapper for hypre's ParCSR matrix class.
Definition hypre.hpp:419
HYPRE_BigInt * ColPart()
Returns the column partitioning.
Definition hypre.hpp:648
void EliminateRows(const Array< int > &rows)
Eliminate rows from the diagonal and off-diagonal blocks of the matrix.
Definition hypre.cpp:2438
void InvScaleRows(const Vector &s)
Scale the local row i by 1./s(i)
Definition hypre.cpp:2183
HYPRE_BigInt GetGlobalNumRows() const
Return the global number of rows.
Definition hypre.hpp:710
HYPRE_BigInt GetGlobalNumCols() const
Return the global number of columns.
Definition hypre.hpp:714
HYPRE_Int Mult(HypreParVector &x, HypreParVector &y, real_t alpha=1.0, real_t beta=0.0) const
Computes y = alpha * A * x + beta * y.
Definition hypre.cpp:1863
MPI_Comm GetComm() const
MPI communicator.
Definition hypre.hpp:609
HYPRE_BigInt * RowPart()
Returns the row partitioning.
Definition hypre.hpp:644
HypreParMatrix * Transpose() const
Returns the transpose of *this.
Definition hypre.cpp:1732
void MergeDiagAndOffd(SparseMatrix &merged)
Get a single SparseMatrix containing all rows from this processor, merged from the diagonal and off-d...
Definition hypre.cpp:1684
HypreParMatrix * EliminateCols(const Array< int > &cols)
Definition hypre.cpp:2424
static bool Root()
Return true if the rank in MPI_COMM_WORLD is zero.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:66
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition operator.hpp:72
void FormContactSystem(ParGridFunction *coords_, const Vector &xref)
Build contact system, assemble gap Jacobian and mass matrices.
real_t E(const Vector &d, int &eval_err)
Evaluate elastic energy functional.
HYPRE_BigInt * GetConstraintsStarts()
Get distributed constraint partition offsets.
void CalcObjectiveGrad(const BlockVector &, BlockVector &)
Compute gradient of objective functional.
void ActivateBoundConstraints()
Activate bound constraints (if enabled).
void DdE(const Vector &d, Vector &gradE)
Evaluate gradient of energy functional.
HypreParMatrix * Dmc(const BlockVector &)
Jacobian of the constraints wrt slack variables.
OptContactProblem(ElasticityOperator *problem_, const std::set< int > &mortar_attrs_, const std::set< int > &nonmortar_attrs_, real_t tribol_ratio_, bool bound_constraints_)
HypreParMatrix * DddE(const Vector &d)
Return Hessian of energy functional.
HypreParMatrix * GetContactSubspaceTransferOperator()
Return transfer operator from contact to displacement subspace.
real_t CalcObjective(const BlockVector &, int &)
Compute objective functional value.
HypreParMatrix * SetupTribol(ParMesh *pmesh, ParGridFunction *coords, const Array< int > &ess_tdofs, const std::set< int > &mortar_attrs, const std::set< int > &non_mortar_attrs, Vector &gap, real_t tribol_ratio)
Get Gap and its Jacobian from Tribol.
void SetDisplacement(const Vector &dx, bool active_constraints)
Update displacement and eps for bound constraints.
HypreParMatrix * Duc(const BlockVector &)
Jacobian of the constraints wrt displacement.
HYPRE_BigInt GetGlobalNumConstraints()
Return global number of constraints.
void c(const BlockVector &, Vector &)
Evaluate contact constraints.
HYPRE_BigInt * GetDofStarts()
Get distributed DOF partition offsets.
void g(const Vector &, Vector &)
Evaluate gap function.
HYPRE_BigInt GetGlobalNumDofs()
Return global number of DOFs (from Jacobian).
Class for parallel bilinear form.
void Assemble(int skip_zeros=1)
Assemble the local matrix.
void FormSystemMatrix(const Array< int > &ess_tdof_list, OperatorHandle &A) override
Form the linear system matrix A, see FormLinearSystem() for details.
HYPRE_BigInt * GetTrueDofOffsets() const
Definition pfespace.hpp:346
HYPRE_BigInt GlobalTrueVSize() const
Definition pfespace.hpp:349
HYPRE_BigInt GetMyTDofOffset() const
Class for parallel grid function.
Definition pgridfunc.hpp:50
Class for parallel meshes.
Definition pmesh.hpp:34
Data type sparse matrix.
Definition sparsemat.hpp:51
real_t GetRowNorml1(int irow) const
For i = irow compute .
bool RowIsEmpty(const int row) const
int NumNonZeroElems() const override
Returns the number of the nonzero elements in the matrix.
real_t * GetData()
Return the element data, i.e. the array A.
void Finalize(int skip_zeros=1) override
Finalize the matrix initialization, switching the storage format from LIL to CSR.
int * GetJ()
Return the array J.
int * GetI()
Return the array I.
void Set(const int i, const int j, const real_t val)
Vector data type.
Definition vector.hpp:82
void SetDataAndSize(real_t *d, int s)
Set the Vector data and size.
Definition vector.hpp:191
real_t Normlinf() const
Returns the l_infinity norm of the vector.
Definition vector.cpp:1004
void SetSubVector(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value.
Definition vector.cpp:702
Vector & Set(const real_t a, const Vector &x)
(*this) = a * x
Definition vector.cpp:341
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:584
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:243
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
Definition vector.cpp:676
Vector & Add(const real_t a, const Vector &Va)
(*this) += a * Va
Definition vector.cpp:326
int problem
Definition ex15.cpp:62
HYPRE_Int HYPRE_BigInt
real_t infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
Definition vector.hpp:47
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition table.cpp:505
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition globals.hpp:66
real_t GlobalLpNorm(const real_t p, real_t loc_norm, MPI_Comm comm)
Compute a global Lp norm from the local Lp norms computed by each processor.
bool IsFinite(const real_t &val)
Definition vector.hpp:553
real_t InnerProduct(HypreParVector *x, HypreParVector *y)
Definition hypre.cpp:468
HypreParMatrix * HypreParMatrixFromBlocks(Array2D< const HypreParMatrix * > &blocks, Array2D< real_t > *blockCoeff)
Returns a merged hypre matrix constructed from hypre matrix blocks.
Definition hypre.cpp:3201
void HypreStealOwnership(HypreParMatrix &A_hyp, SparseMatrix &A_diag)
Make A_hyp steal ownership of its diagonal part A_diag.
Definition hypre.cpp:2912
float real_t
Definition config.hpp:46
Helper struct to convert a C++ type to an MPI type.