29template <
int DIM>
struct QFunction
35 MFEM_HOST_DEVICE
inline auto operator()(
const matd_t &dudxi,
43 return tuple{(L *
tr(eps) * I + 2.0 * M * eps) * JxW};
53 dim(mesh->Dimension()),
54 spaceDim(mesh->SpaceDimension()),
59 sol(vfes->GetTrueVSize()),
60 adj(vfes->GetTrueVSize()),
61 rhs(vfes->GetTrueVSize()),
66 lor_block_offsets(
dim + 1),
75 nodes((pmesh->EnsureNodes(),
77 mfes(
nodes->ParFESpace()),
79 fe->GetOrder() + fe->GetOrder() + fe->GetDim() - 1)),
81 Lambda_ps(*pmesh, ir, 1),
86 "QuadratureSpace and ParameterSpace size mismatch");
100 lcsurf_load = std::make_unique<SurfaceLoad>(dim, load_coeff);
101 glsurf_load = std::make_unique<SurfaceLoad>(dim, surf_loads);
106 domain_attributes = 1;
123 for (
auto it = load_coeff.begin(); it != load_coeff.end(); it++)
170 MFEM_ABORT(
"Invalid BC direction: "
171 "0(x), 1(y), 2(z), or -1(all), got " << dir);
190 if (dir == 0) { bccx[id] = &val; }
191 else if (dir == 1) { bccy[id] = &val; }
192 else if (dir == 2) { bccz[id] = &val; }
201 MFEM_ABORT(
"Invalid BC direction: "
202 "0(x), 1(y), 2(z), or -1(all), got " << dir);
204 if (pmesh->
Dimension() == 2) { bccz.clear(); }
213 if (dim == 3) { ff(2) = fz; }
232 if (j == 1) { cbcc = &bccy; }
233 else if (j == 2) { cbcc = &bccz; }
237 for (
auto it = cbcc->begin(); it != cbcc->end(); it++)
239 ess_bdr[it->first - 1] = 1;
252 for (
auto it = bccx.begin(); it != bccx.end(); it++)
256 ess_bdr[it->first - 1] = 1;
259 ess_tdofx.
Append(ess_tdof_list);
262 pcoeff.
Set(0, it->second,
false);
268 const int Net = ess_tdofx.
Size();
269 const auto d_vc = vc.
Read();
270 const auto d_ess_tdofx = ess_tdofx.
Read();
274 d_bsol[d_ess_tdofx[ii]] = d_vc[d_ess_tdofx[ii]];
278 ess_dofs.
Append(ess_tdofx);
281 for (
auto it = bccy.begin(); it != bccy.end(); it++)
285 ess_bdr[it->first - 1] = 1;
288 ess_tdofy.
Append(ess_tdof_list);
291 pcoeff.
Set(1, it->second,
false);
297 const int Net = ess_tdofy.
Size();
298 const auto d_vc = vc.
Read();
299 const auto d_ess_tdofy = ess_tdofy.
Read();
303 d_bsol[d_ess_tdofy[ii]] = d_vc[d_ess_tdofy[ii]];
307 ess_dofs.
Append(ess_tdofy);
312 for (
auto it = bccz.begin(); it != bccz.end(); it++)
316 ess_bdr[it->first - 1] = 1;
319 ess_tdofz.
Append(ess_tdof_list);
322 pcoeff.
Set(2, it->second,
false);
329 for (
int ii = 0; ii < ess_tdofz.
Size(); ii++)
331 bsol[ess_tdofz[ii]] = vc[ess_tdofz[ii]];
334 ess_dofs.
Append(ess_tdofz);
345 int N = ess_tdofv.
Size();
348 const int *ep = ess_tdofv.
Read();
349 mfem::forall(N, [=] MFEM_HOST_DEVICE(
int i) { yp[ep[i]] = sp[ep[i]]; });
359 int N = ess_tdofv.
Size();
363 const auto ep = ess_tdofv.
Read();
365 mfem::forall(N, [=] MFEM_HOST_DEVICE(
int i) { yp[ep[i]] = 0.0; });
370 delete bf; bf=
nullptr;
374#ifdef MFEM_USE_DOUBLE
376 dop = std::make_unique<mfem::future::DifferentiableOperator>(
377 std::vector<mfem::future::FieldDescriptor> {{ U, vfes }},
378 std::vector<mfem::future::FieldDescriptor>
380 { LCoeff, &Lambda_ps},
387 Lambda_cv = std::make_unique<CoefficientVector>(*lambda, qs);
390 Mu_cv = std::make_unique<CoefficientVector>(*mu, qs);
404 typename QFunction<2>::Elasticity e2qf;
407 else if (3 == spaceDim)
409 typename QFunction<3>::Elasticity e3qf;
412 else { MFEM_ABORT(
"Space dimension not supported"); }
414 MFEM_ABORT(
"Differentiable operator is only supported in double precision");
434 Kh = std::make_unique<OperatorHandle>(Kop);
441 Kh = std::make_unique<OperatorHandle>(Kop);
458 lor_disc = std::make_unique<ParLORDiscretization>(*vfes);
462 lor_scalar_fespace = std::make_unique<ParFiniteElementSpace>(
464 lor_block_offsets[0] = 0;
465 lor_integrator = std::make_unique<ElasticityIntegrator>(*lambda, *mu);
468 for (
int j = 0; j < dim; j++)
472 lor_bilinear_forms.emplace_back(
new ParBilinearForm(lor_scalar_fespace.get()));
473 lor_bilinear_forms[j]->SetAssemblyLevel(AssemblyLevel::FULL);
475 lor_bilinear_forms[j]->AddDomainIntegrator(block);
476 lor_bilinear_forms[j]->Assemble();
479 SetEssTDofs(j,*lor_scalar_fespace,ess_tdof_list_block);
480 lor_block.emplace_back(lor_bilinear_forms[j]->ParallelAssemble());
481 lor_block[j]->EliminateBC(ess_tdof_list_block,
482 Operator::DiagonalPolicy::DIAG_ONE);
484 lor_amg_blocks[j]->SetStrengthThresh(0.25);
485 lor_amg_blocks[j]->SetRelaxType(16);
486 lor_amg_blocks[j]->SetOperator(*lor_block[j]);
487 lor_block_offsets[j+1] = lor_amg_blocks[j]->Height();
492 std::make_unique<BlockDiagonalPreconditioner>(lor_block_offsets);
493 for (
int i = 0; i <
dim; i++)
497 lor_pa_prec.reset(lor_blockDiag.release());
525 if (volforce !=
nullptr)
void SetEssTDofs(mfem::Vector &bsol, mfem::Array< int > &ess_dofs)
void AddDispBC(int id, int dir, real_t val)
Adds displacement BC in direction 0(x), 1(y), 2(z), or -1(all).
void FSolve()
Solves the forward problem.
void SetVolForce(real_t fx, real_t fy, real_t fz=0.0)
Set the values of the volumetric force.
void Mult(const mfem::Vector &x, mfem::Vector &y) const override
Forward solve with given RHS. x is the RHS vector.
void SetLinearSolver(real_t rtol=1e-8, real_t atol=1e-12, int miter=200)
IsoLinElasticSolver(mfem::ParMesh *mesh, int vorder=1, bool pa=false, bool dfem=false)
~IsoLinElasticSolver()
Destructor of the solver.
void MultTranspose(const mfem::Vector &x, mfem::Vector &y) const override
void DelDispBC()
Clear all displacement BC.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
void PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
void DeleteAll()
Delete the whole array.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
void SetDiagonalBlock(int iblock, Operator *op)
Add a square block op in the block-entry (iblock, iblock).
Conjugate gradient method.
void Mult(const Vector &b, Vector &x) const override
Iterative solution of the linear system using the Conjugate Gradient method.
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
A coefficient that is constant across space and time.
Square Operator for imposing essential boundary conditions using only the action, Mult(),...
void EliminateRHS(const Vector &x, Vector &b) const
Eliminate "essential boundary condition" values specified in x from the given right-hand side b.
static bool IsEnabled()
Return true if any backend other than Backend::CPU is enabled.
Integrator that computes the PA action of one of the blocks in an ElasticityIntegrator,...
void AssemblePA(const FiniteElementSpace &fes) override
Method defining partial assembly.
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
const FiniteElementCollection * FEColl() const
const Vector & GetTrueVector() const
Read only access to the (optional) internal true-dof Vector.
Arbitrary order H1-conforming (continuous) finite elements.
The BoomerAMG solver in hypre.
void SetElasticityOptions(ParFiniteElementSpace *fespace, bool interp_refine=true)
void EliminateRowsCols(const Array< int > &rows_cols, const HypreParVector &X, HypreParVector &B)
void EliminateBC(const HypreParMatrix &Ae, const Array< int > &ess_dof_list, const Vector &X, Vector &B) const
Eliminate essential BC specified by ess_dof_list from the solution X to the r.h.s....
void SetRelTol(real_t rtol)
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
void SetMaxIter(int max_it)
void SetAbsTol(real_t atol)
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
int Dimension() const
Dimension of the reference space used within the elements.
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Operator * Ptr() const
Access the underlying Operator pointer.
int width
Dimension of the input / number of columns in the matrix.
void FormSystemOperator(const Array< int > &ess_tdof_list, Operator *&A)
Return in A a parallel (on truedofs) version of this square operator.
int height
Dimension of the output / number of rows in the matrix.
The ordering method used when the number of unknowns per mesh node (vector dimension) is bigger than ...
Abstract parallel finite element space.
void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const override
int GetTrueVSize() const override
Return the number of local vector true dofs.
ParMesh * GetParMesh() const
Class for parallel grid function.
void ProjectBdrCoefficient(Coefficient *coeff[], VectorCoefficient *vcoeff, const Array< int > &attr)
ParFiniteElementSpace & GetParFESpace() const
Return the LOR ParFiniteElementSpace.
Class for parallel meshes.
int GetSize() const
Return the total number of quadrature points.
Vector coefficient defined by an array of scalar coefficients. Coefficients that are not set will eva...
void Set(int i, Coefficient *c, bool own=true)
Sets coefficient in the vector.
Base class for vector Coefficients that optionally depend on time and space.
Vector coefficient that is constant in space and time.
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
virtual real_t * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
void SetParameters(std::vector< Vector * > p) const
Set the parameters for the operator.
void AddDomainIntegrator(qfunc_t &qfunc, input_t inputs, output_t outputs, const IntegrationRule &integration_rule, const Array< int > &domain_attributes, derivative_ids_t derivative_ids=std::make_index_sequence< 0 > {})
Add a domain integrator to the operator.
MFEM_HOST_DEVICE constexpr isotropic_tensor< real_t, m, m > IsotropicIdentity()
MFEM_HOST_DEVICE T det(const tensor< T, 1, 1 > &A)
Returns the determinant of a matrix.
MFEM_HOST_DEVICE T tr(const tensor< T, n, n > &A)
Returns the trace of a square matrix.
MFEM_HOST_DEVICE tensor< T, 1, 1 > inv(const tensor< T, 1, 1 > &A)
Inverts a matrix.
MFEM_HOST_DEVICE tensor< T, n, m > transpose(const tensor< T, m, n > &A)
Returns the transpose of the matrix.
MFEM_HOST_DEVICE tensor< T, n, n > sym(const tensor< T, n, n > &A)
Returns the symmetric part of a square matrix.
void forall(int N, lambda &&body)
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Dual number struct (value plus gradient)
This is a class that mimics most of std::tuple's interface, except that it is usable in CUDA kernels ...
std::array< int, NCMesh::MaxFaceNodes > nodes