asmhandler_impl.hpp
Go to the documentation of this file.
1 //==============================================================================
11 //==============================================================================
12 #ifndef ASMHANDLER_IMPL_HPP_
13 #define ASMHANDLER_IMPL_HPP_
14 
15 #include <dune/common/version.hh>
16 #include <iostream>
17 
18 namespace Opm {
19 namespace Elasticity {
20 
21  template<class GridType>
23 {
24  resolveMPCChains();
25  preprocess();
26  determineAdjacencyPattern();
27 
28  MatrixOps::fromAdjacency(A,adjacencyPattern,
29  adjacencyPattern.size(),adjacencyPattern.size());
30  b.resize(adjacencyPattern.size());
31  b = 0;
32  adjacencyPattern.clear();
33 
34  // print some information
35  std::cout << "\tNumber of nodes: " << gv.size(dim) << std::endl;
36  std::cout << "\tNumber of elements: " << gv.size(0) << std::endl;
37  std::cout << "\tNumber of constraints: " << mpcs.size() << std::endl;
38  int fixedDofs=0;
39  for (fixIt it = fixedNodes.begin(); it != fixedNodes.end(); ++it) {
40  if (it->second.first & X)
41  fixedDofs++;
42  if (it->second.first & Y)
43  fixedDofs++;
44  if (it->second.first & Z)
45  fixedDofs++;
46  }
47  std::cout << "\tNumber of fixed dofs: " << fixedDofs << std::endl;
48 }
49 
50  template<class GridType>
51  template<int esize>
52 void ASMHandler<GridType>::addDOF(int row, int erow,
53  const Dune::FieldMatrix<double,esize,esize>* K,
54  const Dune::FieldVector<double,esize>* S,
55  const LeafIndexSet& set,
56  const LeafIterator& cell,
57  Vector* b,
58  double scale)
59 {
60  if (row == -1)
61  return;
62  if (K) {
63  for (int j=0;j<esize/dim;++j) {
64  int index2 = set.subIndex(*cell,j,dim);
65  for (int l=0;l<dim;++l) {
66  MPC* mpc = getMPC(index2,l);
67  if (mpc) {
68  for (size_t n=0;n<mpc->getNoMaster();++n) {
69  int idx = meqn[mpc->getMaster(n).node*dim+mpc->getMaster(n).dof-1];
70  if (idx != -1)
71  A[row][idx] += scale*mpc->getMaster(n).coeff*(*K)[erow][j*dim+l];
72  }
73  } else if (meqn[index2*dim+l] != -1) {
74  A[row][meqn[index2*dim+l]] += scale*(*K)[erow][j*dim+l];
75  }
76  }
77  }
78  }
79  if (S && b)
80  (*b)[row] += scale*(*S)[erow];
81 }
82 
83  template<class GridType>
84  template<int esize>
86  const Dune::FieldMatrix<double,esize,esize>* K,
87  const Dune::FieldVector<double,esize>* S,
88  const LeafIterator& cell,
89  Vector* b2)
90 {
91  if (!b2)
92  b2 = &b;
93  const LeafIndexSet& set = gv.leafGridView().indexSet();
94  for (int i=0;i<esize/dim;++i) {
95  int index1 = set.subIndex(*cell,i,dim);
96  fixIt it = fixedNodes.find(index1);
97  if (it != fixedNodes.end() && it->second.first == XYZ)
98  continue;
99  for (int k=0;k<dim;++k) {
100  MPC* mpc = getMPC(index1,k);
101  if (mpc) {
102  for (size_t n=0;n<mpc->getNoMaster();++n) {
103  int idx = meqn[mpc->getMaster(n).node*dim+mpc->getMaster(n).dof-1];
104  addDOF(idx,i*dim+k,K,S,set,cell,b2,mpc->getMaster(n).coeff);
105  }
106  } else
107  addDOF(meqn[index1*dim+k],i*dim+k,K,S,set,cell,b2);
108  }
109  }
110 }
111 
112  template<class GridType>
113  template<int comp>
114 void ASMHandler<GridType>::extractValues(Dune::FieldVector<double,comp>& v,
115  const Vector& u,
116  const LeafIterator& it)
117 {
118  v = 0;
119  const LeafIndexSet& set = gv.leafGridView().indexSet();
120  Dune::GeometryType gt = it->type();
121 
122  const Dune::template ReferenceElement<double,dim> &ref =
123  Dune::ReferenceElements<double,dim>::general(gt);
124  int vertexsize = ref.size(dim);
125  int l=0;
126  for (int i=0;i<vertexsize;++i) {
127  int indexi = set.subIndex(*it,i,dim);
128  fixIt it2 = fixedNodes.find(indexi);
129  for (int n=0;n<dim;++n) {
130  MPC* mpc = getMPC(indexi,n);
131  if (it2 != fixedNodes.end() && it2->second.first & (1 << n))
132  v[l++] = it2->second.second[n];
133  else if (mpc) {
134  for (size_t m=0;m<mpc->getNoMaster();++m) {
135  int idx = meqn[mpc->getMaster(m).node*dim+mpc->getMaster(m).dof-1];
136  if (idx != -1)
137  v[l] += u[idx]*mpc->getMaster(m).coeff;
138  }
139  l++;
140  } else
141  v[l++] = u[meqn[indexi*dim+n]];
142  }
143  }
144 }
145 
146  template<class GridType>
148 {
149  int nodes = gv.size(dim);
150  result.resize(nodes*dim);
151  result = 0;
152  int l=0;
153  for (int i=0;i<nodes;++i) {
154  fixIt it = fixedNodes.find(i);
155  Direction dir;
156  if (it == fixedNodes.end())
157  dir = NONE;
158  else
159  dir = it->second.first;
160 
161  int flag=1;
162  for (int j=0;j<dim;++j) {
163  if (dir & flag)
164  result[l] = it->second.second[j];
165  else if (meqn[l] != -1)
166  result[l] = u[meqn[l]];
167  l++;
168  flag *= 2;
169  }
170  }
171  // second loop - handle MPC couplings
172  l = 0;
173  for (int i=0;i<nodes;++i) {
174  for (int j=0;j<dim;++j) {
175  MPC* mpc = getMPC(i,j);
176  if (mpc) {
177  for (size_t n=0;n<mpc->getNoMaster();++n) {
178  int idx = mpc->getMaster(n).node*dim+mpc->getMaster(n).dof-1;
179  if (meqn[idx] != -1)
180  result[l] += u[meqn[idx]]*mpc->getMaster(n).coeff;
181  }
182  }
183  ++l;
184  }
185  }
186 }
187 
188  template<class GridType>
190 {
191  if (!mpc)
192  return;
193 
194  int slaveNode = mpc->getSlave().node*dim+mpc->getSlave().dof-1;
195  fixIt it = fixedNodes.find(mpc->getSlave().node);
196  int flag = 1 << (mpc->getSlave().dof-1);
197  if (it == fixedNodes.end() ||
198  !(it->second.first & flag)) {
199  mpcs.insert(std::make_pair(slaveNode,mpc));
200  return;
201  }
202 
203  delete mpc;
204 }
205 
206  template<class GridType>
208 {
209  if (mpcs.find(node*dim+dof) != mpcs.end())
210  return mpcs[node*dim+dof];
211 
212  return NULL;
213 }
214 
215  template<class GridType>
217  const std::pair<Direction,NodeValue>& entry)
218 {
219  fixIt it = fixedNodes.find(node);
220  // same type or new - update values/add and return
221  if (it == fixedNodes.end() || it->second.first == entry.first) {
222  fixedNodes[node] = entry;
223  return;
224  }
225  int temp = it->second.first;
226  temp |= entry.first;
227  it->second.first = (Direction)temp;
228  int flag = 1;
229  for (int i=0;i<dim;++i) {
230  if (entry.first & flag)
231  it->second.second[i] = entry.second[i];
232  flag *= 2;
233  }
234 }
235 
236  template<class GridType>
238 {
239  MatrixOps::print(A);
240 }
241 
242  template<class GridType>
244 {
245  for (int i=0;i<b.size();++i) {
246  double val = b[i];
247  std::cout << (fabs(val)>1.e-12?val:0.f) << std::endl;
248  }
249 }
250 
251  template<class GridType>
253 {
254  size_t nMaster = mpc->getNoMaster();
255  if (nMaster == 0) return; // no masters, prescribed displacement only
256 
257  for (size_t i = 0; i < nMaster; i++)
258  {
259  // Check if the master node has a local coordinate system attached. If yes,
260  // the slave DOF might be coupled to all (local) DOFs of the master node.
261  const MPC::DOF& master = mpc->getMaster(i);
262  Dune::FieldVector<double,dim> coeff;
263  coeff = 0;
264  coeff[master.dof-1] = master.coeff;
265 
266  int removeOld = 0;
267  for (int d = 1; d <= dim; d++)
268  if (fabs(coeff[d-1]) > 1.0e-8)
269  {
270  MPC* mpc2 = getMPC(mpc->getMaster(i).node,d-1);
271  if (mpc2)
272  {
273  // We have a master DOF which is a slave in another MPC.
274  // Invoke resolveMPCchain recursively to ensure that all master DOFs
275  // of that equation are not slaves themselves.
276  resolveMPCChain(mpc2);
277 
278  // Remove current master specification, unless it has been updated
279  if (!removeOld) removeOld = 1;
280 
281  // Add constant offset from the other equation
282  mpc->addOffset(mpc2->getSlave().coeff*coeff[d-1]);
283 
284  // Add masters from the other equations
285  for (size_t j = 0; j < mpc2->getNoMaster(); j++)
286  mpc->addMaster(mpc2->getMaster(j).node,
287  mpc2->getMaster(j).dof,
288  mpc2->getMaster(j).coeff*coeff[d-1]);
289  }
290  else
291  // The master node is free, but has a local coordinate system
292  if (d != mpc->getMaster(i).dof)
293  // Add coupling to the other local DOFs of this master node.
294  mpc->addMaster(mpc->getMaster(i).node,d,coeff[d-1]);
295  else if (coeff[d-1] != mpc->getMaster(i).coeff)
296  {
297  // Update the coupling coefficient of this master DOF
298  // due to the local-to-global transformation
299  mpc->updateMaster(i,coeff[d-1]);
300  removeOld = -1;
301  }
302  }
303  else if (d == mpc->getMaster(i).dof && !removeOld)
304  // The coefficient of the current master DOF is zero,
305  removeOld = 1; // so remove it from the contraint equation
306 
307  if (removeOld == 1)
308  {
309  // Remove the old master DOF specification when it has been replaced
310  mpc->removeMaster(i--);
311  nMaster--; // we don't need to check the added masters
312  }
313  }
314 }
315 
316  template<class GridType>
318 {
319  int nodes = gv.size(dim);
320  meqn.resize(nodes*dim);
321 
322  // iterate over nodes
323  for (int indexi=0;indexi<nodes;++indexi) {
324  fixIt it2 = fixedNodes.find(indexi);
325  if (it2 == fixedNodes.end()) {
326  for (int i=0;i<dim;++i) {
327  MPC* mpc = getMPC(indexi,i);
328  if (!mpc)
329  meqn[indexi*dim+i] = maxeqn++;
330  else
331  meqn[indexi*dim+i] = -1;
332  }
333  } else {
334  int flag=1;
335  for (int i=0;i<dim;++i) {
336  if (it2->second.first & flag)
337  meqn[indexi*dim+i] = -1;
338  else {
339  MPC* mpc = getMPC(indexi,i);
340  if (!mpc)
341  meqn[indexi*dim+i] = maxeqn++;
342  else
343  meqn[indexi*dim+i] = -1;
344  }
345  flag *= 2;
346  }
347  }
348  }
349  std::cout << "\tnumber of equations: " << maxeqn << std::endl;
350 }
351 
352  template<class GridType>
354  int vertexsize, int row)
355 {
356  if (row == -1)
357  return;
358  const LeafIndexSet& set = gv.leafGridView().indexSet();
359  for (int j=0;j<vertexsize;++j) {
360  int indexj = set.subIndex(*it,j,dim);
361  for (int l=0;l<dim;++l) {
362  MPC* mpc = getMPC(indexj,l);
363  if (mpc) {
364  for (size_t i=0;i<mpc->getNoMaster();++i) {
365  int idx = meqn[mpc->getMaster(i).node*dim+
366  mpc->getMaster(i).dof-1];
367  if (idx != -1)
368  adjacencyPattern[row].insert(idx);
369  }
370  } else if (meqn[indexj*dim+l] != -1)
371  adjacencyPattern[row].insert(meqn[indexj*dim+l]);
372  }
373  }
374 }
375 
376  template<class GridType>
378 {
379  adjacencyPattern.resize(maxeqn);
380  std::cout << "\tsetting up sparsity pattern..." << std::endl;
381  LoggerHelper help(gv.size(0), 5, 50000);
382 
383  const LeafIndexSet& set = gv.leafGridView().indexSet();
384  LeafIterator itend = gv.leafGridView().template end<0>();
385 
386  // iterate over cells
387  int cell=0;
388  for (LeafIterator it = gv.leafGridView().template begin<0>(); it != itend; ++it, ++cell) {
389  Dune::GeometryType gt = it->type();
390 
391  const Dune::template ReferenceElement<double,dim>& ref =
392  Dune::ReferenceElements<double,dim>::general(gt);
393 
394  int vertexsize = ref.size(dim);
395  for (int i=0; i < vertexsize; i++) {
396  int indexi = set.subIndex(*it,i,dim);
397  for (int k=0;k<dim;++k) {
398  MPC* mpc = getMPC(indexi,k);
399  if (mpc) {
400  for (size_t l=0;l<mpc->getNoMaster();++l) {
401  nodeAdjacency(it,vertexsize,
402  meqn[mpc->getMaster(l).node*dim+
403  mpc->getMaster(l).dof-1]);
404  }
405  } else
406  nodeAdjacency(it,vertexsize,meqn[indexi*dim+k]);
407  }
408  }
409  if (cell % 10000 == 0)
410  help.log(cell, "\t\t... still processing ... cell ");
411  }
412 }
413 
414 }} // namespace Opm, Elasticity
415 
416 #endif
void removeMaster(size_t pos)
Removes the pos'th master DOF from the constraint equation.
Definition: mpc.hh:126
void printLoadVector() const
Print the current load vector.
Definition: asmhandler_impl.hpp:243
Definition: applier.hpp:18
void addDOF(int row, int erow, const Dune::FieldMatrix< double, esize, esize > *K, const Dune::FieldVector< double, esize > *S, const LeafIndexSet &set, const LeafIterator &cell, Vector *b, double scale=1.f)
Internal function. Assemble entries for a single DOF.
Definition: asmhandler_impl.hpp:52
const DOF & getSlave() const
Returns a reference to the slave DOF.
Definition: mpc.hh:139
int node
Node number identifying this DOF.
Definition: mpc.hh:83
Definition: mpc.hh:26
void preprocess()
Internal function. Generate meqn for registered MPC/fixed nodes.
Definition: asmhandler_impl.hpp:317
GridType::LeafGridView::template Codim< 0 >::Iterator LeafIterator
An iterator over grid cells.
Definition: asmhandler.hpp:38
void extractValues(Dune::FieldVector< double, comp > &v, const Vector &u, const LeafIterator &it)
Extract values corresponding to cell.
Definition: asmhandler_impl.hpp:114
A class for representing a general multi-point constraint equation.
Definition: mpc.hh:58
void addElement(const Dune::FieldMatrix< double, esize, esize > *K, const Dune::FieldVector< double, esize > *S, const LeafIterator &cell, Vector *b=NULL)
Add an element matrix/vector to the system.
Definition: asmhandler_impl.hpp:85
const DOF & getMaster(size_t i) const
Returns a reference to the i'th master DOF.
Definition: mpc.hh:141
void expandSolution(Vector &result, const Vector &u)
Expand a system vector to a solution vector.
Definition: asmhandler_impl.hpp:147
Definition: mpc.hh:24
void resolveMPCChain(MPC *mpc)
Internal function. Handles a single MPC.
Definition: asmhandler_impl.hpp:252
size_t getNoMaster() const
Returns the number of master DOFs.
Definition: mpc.hh:144
static void fromAdjacency(Matrix &A, const AdjacencyPattern &adj, int rows, int cols)
Create a sparse matrix from a given adjacency pattern.
void updateFixedNode(int node, const std::pair< Direction, NodeValue > &entry)
Update/add a fixed node.
Definition: asmhandler_impl.hpp:216
void determineAdjacencyPattern()
Internal function. Calculate adjacency pattern.
Definition: asmhandler_impl.hpp:377
void printOperator() const
Print the current operator.
Definition: asmhandler_impl.hpp:237
void nodeAdjacency(const LeafIterator &it, int vertexsize, int row)
Internal function. Generate adjacency pattern for a given node.
Definition: asmhandler_impl.hpp:353
static void print(const Matrix &A)
Print a matrix to stdout.
void updateMaster(size_t pos, double c)
Updates the coefficient of the pos'th master DOF.
Definition: mpc.hh:119
Definition: mpc.hh:24
int dof
Local DOF number within node.
Definition: mpc.hh:84
void addOffset(double offset)
Increments the c0 coefficient by a given offset.
Definition: mpc.hh:133
void initForAssembly()
This function needs to be called before starting the element assembly.
Definition: asmhandler_impl.hpp:22
Definition: mpc.hh:24
Direction
An enum for specification of global coordinate directions.
Definition: mpc.hh:24
void addMPC(MPC *mpc)
Add a MPC.
Definition: asmhandler_impl.hpp:189
A struct for representing one term (DOF number and associated coefficient) in a MPC equation...
Definition: mpc.hh:66
double coeff
The constrained value, or master DOF scaling coefficient.
Definition: mpc.hh:85
Definition: mpc.hh:24
MPC * getMPC(int node, int dof)
Look for and return a MPC for a specified node+dof.
Definition: asmhandler_impl.hpp:207
Dune::BlockVector< Dune::FieldVector< double, 1 > > Vector
A vector holding our RHS.
Definition: matrixops.hpp:29
const LeafVertexIterator itend
Definition: elasticity_upscale_impl.hpp:145
GridType::LeafGridView::IndexSet LeafIndexSet
A set of indices.
Definition: asmhandler.hpp:35
Helper class for progress logging during time consuming processes.
Definition: logutils.hpp:21
int j
Definition: elasticity_upscale_impl.hpp:658
void addMaster(int n, int d, double c=double(1), double tol=double(1.0e-8))
Adds a master DOF to the constraint equation.
Definition: mpc.hh:113
fixMap::iterator fixIt
Iterator over a fixmap.
Definition: asmhandler.hpp:205