G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsVisitorBiharmonic.h
1 
15 #pragma once
16 
18 #include <gsCore/gsFuncData.h>
19 
20 namespace gismo
21 {
22 
23 template <class T>
24 class gsVisitorBiharmonic
25 {
26 public:
27 
28  gsVisitorBiharmonic(const gsPde<T> & pde_, gsSparseMatrix<T> * elimMatrix = nullptr)
29  : pde_ptr(static_cast<const gsPoissonPde<T>*>(&pde_)),
30  elimMat(elimMatrix)
31  {}
32 
33  void initialize(const gsBasisRefs<T> & basisRefs,
34  const index_t patchIndex,
35  const gsOptionList & options,
36  gsQuadRule<T> & rule)
37  {
38  // a quadrature rule is defined by the basis for the auxiliary variable.
39  // the same rule is used for the main variable
40  rule = gsQuadrature::get(basisRefs.back(), options);
41  // saving necessary info
42  localStiffening = options.getReal("LocalStiff");
43  // resize containers for global indices
44  globalIndices.resize(2);
45  blockNumbers.resize(2);
46  }
47 
48  inline void evaluate(const gsBasisRefs<T> & basisRefs,
49  const gsGeometry<T> & geo,
50  const gsMatrix<T> & quNodes)
51  {
52  // store quadrature points of the element for geometry evaluation
53  md.points = quNodes;
54  // NEED_VALUE to get points in the physical domain for evaluation of the RHS
55  // NEED_MEASURE to get the Jacobian determinant values for integration
56  // NEED_GRAD_TRANSFORM to get the Jacobian matrix to transform gradient from the parametric to physical domain
58  // Compute image of the quadrature points plus gradient, jacobian and other necessary data
59  geo.computeMap(md);
60  // find local indices of the main and auxiliary basis functions active on the element
61  basisRefs.front().active_into(quNodes.col(0),localIndicesMain);
62  N_M = localIndicesMain.rows();
63  basisRefs.back().active_into(quNodes.col(0), localIndicesAux);
64  N_A = localIndicesAux.rows();
65  // Evaluate basis functions and their derivatives on the element
66  basisRefs.front().evalAllDers_into(quNodes,1,basisValuesMain);
67  basisRefs.back().evalAllDers_into(quNodes,1,basisValuesAux);
68  // Evaluate right-hand side at the image of the quadrature points
69  pde_ptr->rhs()->eval_into(md.values[0],forceValues);
70  }
71 
72  inline void assemble(gsDomainIterator<T> & element,
73  const gsVector<T> & quWeights)
74  {
75  // Initialize local matrix/rhs // 0 | B^T = L
76  localMat.setZero(N_M + N_A, N_M + N_A); // --|-- matrix structure
77  localRhs.setZero(N_M + N_A,pde_ptr->numRhs()); // B | A = 0
78 
79  // Loop over the quadrature nodes
80  for (index_t q = 0; q < quWeights.rows(); ++q)
81  {
82  // Multiply quadrature weight by the geometry measure
83  const T weightMatrix = quWeights[q] * pow(md.measure(q),1-localStiffening);
84  const T weightRHS = quWeights[q] * md.measure(q);
85  // Compute physical gradients of the basis functions at q as a 1 x numActiveFunction matrix
86  transformGradients(md, q, basisValuesAux[1], physGradAux);
87  transformGradients(md, q, basisValuesMain[1], physGradMain);
88  // matrix A
89  block = weightMatrix * basisValuesAux[0].col(q) * basisValuesAux[0].col(q).transpose();
90  localMat.block(N_M,N_M,N_A,N_A) += block.block(0,0,N_A,N_A);
91  // matrix B
92  block = weightMatrix * physGradAux.transpose()*physGradMain; // N_A x N_M
93  localMat.block(0,N_M,N_M,N_A) += block.block(0,0,N_A,N_M).transpose();
94  localMat.block(N_M,0,N_A,N_M) += block.block(0,0,N_A,N_M);
95  // rhs contribution
96  localRhs.middleRows(0,N_M).noalias() += weightRHS * basisValuesMain[0].col(q) * forceValues.col(q).transpose();
97  }
98  }
99 
100  inline void localToGlobal(const int patchIndex,
101  const std::vector<gsMatrix<T> > & eliminatedDofs,
102  gsSparseSystem<T> & system)
103  {
104  // compute global indices
105  system.mapColIndices(localIndicesMain,patchIndex,globalIndices[0],0);
106  system.mapColIndices(localIndicesAux,patchIndex,globalIndices[1],1);
107  blockNumbers.at(0) = 0;
108  blockNumbers.at(1) = 1;
109  // push to global system
110  system.pushToRhs(localRhs,globalIndices,blockNumbers);
111  system.pushToMatrix(localMat,globalIndices,eliminatedDofs,blockNumbers,blockNumbers);
112 
113  // push to the elimination system
114  if (elimMat != nullptr)
115  {
116  index_t globalI,globalElimJ;
117  index_t elimSize = 0;
118  for (short_t dJ = 0; dJ < 2; ++dJ)
119  {
120  for (short_t dI = 0; dI < 2; ++dI)
121  for (index_t i = 0; i < N_M; ++i)
122  if (system.colMapper(dI).is_free_index(globalIndices[dI].at(i)))
123  {
124  system.mapToGlobalRowIndex(localIndicesMain.at(i),patchIndex,globalI,dI);
125  for (index_t j = 0; j < N_M; ++j)
126  if (!system.colMapper(dJ).is_free_index(globalIndices[dJ].at(j)))
127  {
128  globalElimJ = system.colMapper(dJ).global_to_bindex(globalIndices[dJ].at(j));
129  elimMat->coeffRef(globalI,elimSize+globalElimJ) += localMat(N_M*dI+i,N_M*dJ+j);
130  }
131  }
132  elimSize += eliminatedDofs[dJ].rows();
133  }
134  }
135  }
136 
137 protected:
138  // problem info
139  const gsPoissonPde<T> * pde_ptr;
140  // geometry mapping
141  gsMapData<T> md;
142  // local components of the global linear system
143  gsMatrix<T> localMat;
144  gsMatrix<T> localRhs;
145  // local indices (at the current patch) of basis functions active at the current element
146  gsMatrix<index_t> localIndicesMain;
147  gsMatrix<index_t> localIndicesAux;
148  // number of main and auxiliary basis functions active at the current element
149  index_t N_M, N_A;
150  // values and derivatives of main basis functions at quadrature points at the current element
151  // values are stored as a N_M x numQuadPoints matrix; not sure about derivatives, must be smth like N_M x numQuadPoints
152  // same for the auxiliary basis functions
153  std::vector<gsMatrix<T> > basisValuesMain;
154  std::vector<gsMatrix<T> > basisValuesAux;
155  // RHS values at quadrature points at the current element; stored as a 1 x numQuadPoints matrix
156  gsMatrix<T> forceValues;
157  // all temporary matrices defined here for efficiency
158  gsMatrix<T> block, physGradMain, physGradAux;
159  real_t localStiffening;
160  // elimination matrix to efficiently change Dirichlet degrees of freedom
161  gsSparseMatrix<T> * elimMat;
162  // containers for global indices
163  std::vector< gsMatrix<index_t> > globalIndices;
164  gsVector<index_t> blockNumbers;
165 };
166 
167 } // namespace gismo
#define short_t
Definition: gsConfig.h:35
#define index_t
Definition: gsConfig.h:32
T at(index_t i) const
Returns the i-th element of the vectorization of the matrix.
Definition: gsMatrix.h:211
static gsQuadRule< T > get(const gsBasis< T > &basis, const gsOptionList &options, short_t fixDir=-1)
Constructs a quadrature rule based on input options.
Definition: gsQuadrature.h:48
void assemble(gsDomainIterator< T > &, const gsVector< T > &quWeights)
Assemble on element.
Definition: gsVisitorBiharmonic.h:109
T at(index_t i) const
Returns the i-th element of the vector.
Definition: gsVector.h:177
Creates a variety of quadrature rules.
void localToGlobal(const index_t patchIndex, const std::vector< gsMatrix< T > > &eliminatedDofs, gsSparseSystem< T > &system)
Adds the contributions to the sparse system.
Definition: gsVisitorBiharmonic.h:132
The density of the measure pull back.
Definition: gsForwardDeclarations.h:76
gsVisitorBiharmonic(const gsPde< T > &pde)
Constructor.
Definition: gsVisitorBiharmonic.h:39
Value of the object.
Definition: gsForwardDeclarations.h:72
void evaluate(const gsBasis< T > &basis, const gsGeometry< T > &geo, gsMatrix< T > &quNodes)
Evaluate on element.
Definition: gsVisitorBiharmonic.h:81
Gradient transformation matrix.
Definition: gsForwardDeclarations.h:77
void initialize(const gsBasis< T > &basis, gsQuadRule< T > &rule)
Initialize.
Definition: gsVisitorBiharmonic.h:53
This object is a cache for computed values from an evaluator.