// Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-806117. // // This file is part of the MFEM library. For more information and source code // availability visit https://mfem.org. // // MFEM is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. #ifndef MFEM_PRMNONLINEARFORM #define MFEM_PRMNONLINEARFORM #include "mfem.hpp" namespace mfem { /** The abstract base class ParametricBNLFormIntegrator is a generalization of the BlockNonlinearFormIntegrator class suitable for block state and parameter vectors. */ class ParametricBNLFormIntegrator { public: /// Compute the local energy virtual double GetElementEnergy(const Array&el, const Array&pel, ElementTransformation &Tr, const Array&elfun, const Array&pelfun); /// Perform the local action of the BlockNonlinearFormIntegrator virtual void AssembleElementVector(const Array &el, const Array&pel, ElementTransformation &Tr, const Array &elfun, const Array&pelfun, const Array &elvec); /// Perform the local action of the BlockNonlinearFormIntegrator on element /// faces virtual void AssembleFaceVector(const Array &el1, const Array &el2, const Array &pel1, const Array &pel2, FaceElementTransformations &Tr, const Array &elfun, const Array&pelfun, const Array &elvect); /// Perform the local action on the parameters of the BNLFormIntegrator virtual void AssemblePrmElementVector(const Array &el, const Array&pel, ElementTransformation &Tr, const Array &elfun, const Array &alfun, const Array&pelfun, const Array &pelvec); /// Perform the local action on the parameters of the BNLFormIntegrator on /// faces virtual void AssemblePrmFaceVector(const Array &el1, const Array &el2, const Array &pel1, const Array &pel2, FaceElementTransformations &Tr, const Array &elfun, const Array &alfun, const Array&pelfun, const Array &pelvect); /// Assemble the local gradient matrix virtual void AssembleElementGrad(const Array &el, const Array&pel, ElementTransformation &Tr, const Array &elfun, const Array&pelfun, const Array2D &elmats); /// Assemble the local gradient matrix on faces of the elements virtual void AssembleFaceGrad(const Array&el1, const Array&el2, const Array &pel1, const Array &pel2, FaceElementTransformations &Tr, const Array &elfun, const Array&pelfun, const Array2D &elmats); virtual ~ParametricBNLFormIntegrator() { } }; /** @brief A class representing a general parametric block nonlinear operator defined on the Cartesian product of multiple FiniteElementSpace%s. */ class ParametricBNLForm : public Operator { protected: /// FE spaces on which the form lives. Array fes; /// FE spaces for the parametric fields Array paramfes; int paramheight; int paramwidth; /// Set of Domain Integrators to be assembled (added). Array dnfi; /// Set of interior face Integrators to be assembled (added). Array fnfi; /// Set of Boundary Face Integrators to be assembled (added). Array bfnfi; Array*> bfnfi_marker; /** Auxiliary block-vectors for wrapping input and output vectors or holding GridFunction-like block-vector data (e.g. in parallel). */ mutable BlockVector xs, ys; mutable BlockVector prmxs, prmys; /** Auxiliary block-vectors for holding GridFunction-like block-vector data (e.g. in parallel). */ mutable BlockVector xsv; /** Auxiliary block-vectors for holding GridFunction-like block-vector data for the parameter fields (e.g. in parallel). */ mutable BlockVector xdv; /** Auxiliary block-vectors for holding GridFunction-like block-vector data for the adjoint fields (e.g. in parallel). */ mutable BlockVector adv; mutable Array2D Grads, cGrads; mutable BlockOperator *BlockGrad; // A list of the offsets Array block_offsets; Array block_trueOffsets; // A list with the offsets for the parametric fields Array paramblock_offsets; Array paramblock_trueOffsets; // Array of Arrays of tdofs for each space in 'fes' Array *> ess_tdofs; // Array of Arrays of tdofs for each space in 'paramfes' Array *> paramess_tdofs; /// Array of pointers to the prolongation matrix of fes, may be NULL Array P; /// Array of pointers to the prolongation matrix of paramfes, may be NULL Array Pparam; /// Array of results of dynamic-casting P to SparseMatrix pointer Array cP; /// Array of results of dynamic-casting Pparam to SparseMatrix pointer Array cPparam; /// Indicator if the Operator is part of a parallel run bool is_serial = true; /// Indicator if the Operator needs prolongation on assembly bool needs_prolongation = false; /// Indicator if the Operator needs prolongation on assembly bool prmneeds_prolongation = false; mutable BlockVector aux1, aux2; mutable BlockVector prmaux1, prmaux2; const BlockVector &Prolongate(const BlockVector &bx) const; const BlockVector &ParamProlongate(const BlockVector &bx) const; double GetEnergyBlocked(const BlockVector &bx, const BlockVector &dx) const; /// Specialized version of Mult() for BlockVector%s /// Block L-Vector to Block L-Vector void MultBlocked(const BlockVector &bx, const BlockVector &dx, BlockVector &by) const; /// Specialized version of Mult() for BlockVector%s /// Block L-Vector to Block L-Vector /// bx - state vector, ax - adjoint vector, dx - parametric fields /// dy = ax' d(residual(bx))/d(dx) void MultParamBlocked(const BlockVector &bx, const BlockVector & ax, const BlockVector &dx, BlockVector &dy) const; /// Specialized version of GetGradient() for BlockVector void ComputeGradientBlocked(const BlockVector &bx, const BlockVector &dx) const; public: /// Construct an empty BlockNonlinearForm. Initialize with SetSpaces(). ParametricBNLForm(); /// Construct a BlockNonlinearForm on the given set of FiniteElementSpace%s. ParametricBNLForm(Array &statef, Array ¶mf); /// Return the @a k-th FE space of the ParametricBNLForm. FiniteElementSpace *FESpace(int k) { return fes[k]; } /// Return the @a k-th parametric FE space of the ParametricBNLForm. FiniteElementSpace *ParamFESpace(int k) { return paramfes[k]; } /// Return the @a k-th FE space of the BlockNonlinearForm (const version). const FiniteElementSpace *FESpace(int k) const { return fes[k]; } /// Return the @a k-th parametric FE space of the BlockNonlinearForm (const /// version). const FiniteElementSpace *ParamFESpace(int k) const { return paramfes[k]; } /// Return the integrators Array& GetDNFI() { return dnfi;} /// (Re)initialize the ParametricBNLForm. /** After a call to SetSpaces(), the essential b.c. must be set again. */ void SetSpaces(Array &statef, Array ¶mf); /// Return the regular dof offsets. const Array &GetBlockOffsets() const { return block_offsets; } /// Return the true-dof offsets. const Array &GetBlockTrueOffsets() const { return block_trueOffsets; } /// Return the regular dof offsets for the parameters. const Array &ParamGetBlockOffsets() const { return paramblock_offsets; } /// Return the true-dof offsets for the parameters. const Array &ParamGetBlockTrueOffsets() const { return paramblock_trueOffsets; } /// Adds new Domain Integrator. void AddDomainIntegrator(ParametricBNLFormIntegrator *nlfi) { dnfi.Append(nlfi); } /// Adds new Interior Face Integrator. void AddInteriorFaceIntegrator(ParametricBNLFormIntegrator *nlfi) { fnfi.Append(nlfi); } /// Adds new Boundary Face Integrator. void AddBdrFaceIntegrator(ParametricBNLFormIntegrator *nlfi) { bfnfi.Append(nlfi); bfnfi_marker.Append(NULL); } /** @brief Adds new Boundary Face Integrator, restricted to specific boundary attributes. */ void AddBdrFaceIntegrator(ParametricBNLFormIntegrator *nlfi, Array &bdr_marker); /// Set the essential boundary conditions. virtual void SetEssentialBC(const Array *>&bdr_attr_is_ess, Array &rhs); /// Set the essential boundary conditions on the parametric fields. virtual void SetParamEssentialBC(const Array *>&bdr_attr_is_ess, Array &rhs); /// Computes the energy for a state vector x. virtual double GetEnergy(const Vector &x) const; /// Method is only called in serial, the parallel version calls MultBlocked /// directly. virtual void Mult(const Vector &x, Vector &y) const; /// Method is only called in serial, the parallel version calls MultBlocked /// directly. virtual void ParamMult(const Vector &x, Vector &y) const; /// Method is only called in serial, the parallel version calls /// GetGradientBlocked directly. virtual BlockOperator &GetGradient(const Vector &x) const; /// Set the state fields virtual void SetStateFields(const Vector &xv) const; /// Set the adjoint fields virtual void SetAdjointFields(const Vector &av) const; /// Set the parameters/design fields virtual void SetParamFields(const Vector &dv) const; /// Destructor. virtual ~ParametricBNLForm(); }; } #endif