OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
transportgradientdirichlet.C
Go to the documentation of this file.
1 /*
2  *
3  * ##### ##### ###### ###### ### ###
4  * ## ## ## ## ## ## ## ### ##
5  * ## ## ## ## #### #### ## # ##
6  * ## ## ## ## ## ## ## ##
7  * ## ## ## ## ## ## ## ##
8  * ##### ##### ## ###### ## ##
9  *
10  *
11  * OOFEM : Object Oriented Finite Element Code
12  *
13  * Copyright (C) 1993 - 2013 Borek Patzak
14  *
15  *
16  *
17  * Czech Technical University, Faculty of Civil Engineering,
18  * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33  */
34 
36 #include "dofiditem.h"
37 #include "dofmanager.h"
38 #include "dof.h"
39 #include "valuemodetype.h"
40 #include "floatarray.h"
41 #include "floatmatrix.h"
42 #include "function.h"
43 #include "engngm.h"
44 #include "set.h"
45 #include "node.h"
46 #include "element.h"
47 #include "classfactory.h"
48 #include "dynamicinputrecord.h"
49 #include "unknownnumberingscheme.h"
50 #include "sparsemtrx.h"
51 #include "sparselinsystemnm.h"
52 #include "assemblercallback.h"
53 #include "mathfem.h"
54 #include "feinterpol.h"
55 #include "feinterpol3d.h"
56 #include "transportelement.h"
57 #include "gausspoint.h"
58 #include "sparselinsystemnm.h"
59 
60 #include "timer.h" // Benchmarking
61 
62 #include <tuple>
63 #include <vector>
64 #include <algorithm>
65 #include <iterator>
66 
67 namespace oofem {
68 REGISTER_BoundaryCondition(TransportGradientDirichlet);
69 
70 
72 {
73  IRResultType result; // Required by IR_GIVE_FIELD macro
75 
78 
80  if ( this->tractionControl ) {
82  //IR_GIVE_FIELD(ir, edgeSets, _IFT_TransportGradientDirichlet_edgeSets);
83  }
84 
86 }
87 
88 
90 {
94  //input.setField(edgeSets, _IFT_TransportGradientDirichlet_edgeSets);
95  if ( this->tractionControl ) {
97  }
98 
100 }
101 
102 
104 {
106 
107  if ( this->tractionControl ) this->computeXi();
108 }
109 
110 
111 double TransportGradientDirichlet :: give(Dof *dof, ValueModeType mode, double time)
112 {
113  FloatArray *coords = dof->giveDofManager()->giveCoordinates();
114 
115  if ( coords->giveSize() != this->mCenterCoord.giveSize() ) {
116  OOFEM_ERROR("Size of coordinate system different from center coordinate in b.c.");
117  }
118 
119  double factor = 0;
120  if ( mode == VM_Total ) {
121  factor = this->giveTimeFunction()->evaluateAtTime(time);
122  } else if ( mode == VM_Velocity ) {
123  factor = this->giveTimeFunction()->evaluateVelocityAtTime(time);
124  } else if ( mode == VM_Acceleration ) {
125  factor = this->giveTimeFunction()->evaluateAccelerationAtTime(time);
126  } else {
127  OOFEM_ERROR("Should not be called for value mode type then total, velocity, or acceleration.");
128  }
129 
130  // Reminder: u_i = g_i . (x_i - xc_i + xi_i)
131  FloatArray dx;
132  dx.beDifferenceOf(* coords, this->mCenterCoord);
133  // Add "xi" if it is defined. Classical Dirichlet b.c. is retained if this isn't defined (or set to zero).
134  if ( !xis.empty() ) {
135  dx.add(xis[dof->giveDofManager()->giveNumber()]);
136  }
137 
138  return mGradient.dotProduct(dx) * factor;
139 }
140 
141 
143 {
144  Domain *domain = this->giveDomain();
145  int nsd = domain->giveNumberOfSpatialDimensions();
146  double domain_size = 0.0;
147  if ( this->tractionControl ) {
148  for ( auto &surf : this->surfSets ) {
149  const IntArray &boundaries = domain->giveSet(surf)->giveBoundaryList();
150 
151  for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) {
152  Element *e = domain->giveElement( boundaries.at(pos * 2 - 1) );
153  int boundary = boundaries.at(pos * 2);
155  domain_size += fei->evalNXIntegral( boundary, FEIElementGeometryWrapper(e) );
156  }
157  }
158  } else {
159  const IntArray &boundaries = domain->giveSet(this->set)->giveBoundaryList();
160 
161  for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) {
162  Element *e = domain->giveElement( boundaries.at(pos * 2 - 1) );
163  int boundary = boundaries.at(pos * 2);
165  domain_size += fei->evalNXIntegral( boundary, FEIElementGeometryWrapper(e) );
166  }
167  }
168  return fabs(domain_size / nsd);
169 }
170 
171 
173 // v_prescribed = C.g = (x-xbar + xi).g;
174 // C = [x-xi_x y-xi_y]
175 // C = [x-xi_x y-xi_y z-xi_z]
176 {
177  Domain *domain = this->giveDomain();
178 
179  int nsd = domain->giveNumberOfSpatialDimensions();
181  C.resize(npeq, nsd);
182  C.zero();
183 
184  for ( auto &n : domain->giveDofManagers() ) {
185  FloatArray *coords = n->giveCoordinates();
186  Dof *d1 = n->giveDofWithID( this->dofs(0) );
187  int k1 = d1->__givePrescribedEquationNumber();
188  if ( k1 ) {
189  // Add "xi" if it is defined. Classical Dirichlet b.c. is retained if this isn't defined (or set to zero).
190  FloatArray xi(nsd);
191  if ( this->tractionControl ) {
192  xi = xis[n->giveNumber()];
193  }
194  for ( int i = 1; i <= nsd; ++i ) {
195  C.at(k1, i) = coords->at(i) - mCenterCoord.at(i) + xi.at(i);
196  }
197  //printf("C.at(%d, :) = %e, %e, %e\n", k1, C.at(k1, 1), C.at(k1, 2), C.at(k1, 3));
198  }
199  }
200 }
201 
202 
204 {
205  EngngModel *emodel = this->domain->giveEngngModel();
207  FloatArray R_c(npeq), R_ext(npeq);
208 
209  R_c.zero();
210  R_ext.zero();
211  emodel->assembleVector( R_c, tStep, InternalForceAssembler(), VM_Total,
213  emodel->assembleVector( R_ext, tStep, ExternalForceAssembler(), VM_Total,
215  R_c.subtract(R_ext);
216 
217  // Condense it;
218  FloatMatrix C;
219  this->computeCoefficientMatrix(C);
220  sigma.beTProductOf(C, R_c);
221  sigma.times( -1. / this->domainSize() );
222 }
223 
224 
226 // a = [a_c; a_f];
227 // K.a = [R_c,0];
228 // [K_cc, K_cf; K_fc, K_ff].[a_c;a_f] = [R_c; 0];
229 // a_c = d.[x-x_b] = [x-x_b].d = C.d
230 // E = C'.(K_cc - K_cf.K_ff^(-1).K_fc).C
231 // = C'.(K_cc.C - K_cf.(K_ff^(-1).(K_fc.C)))
232 // = C'.(K_cc.C - K_cf.a)
233 // = C'.X
234 {
235  // Fetch some information from the engineering model
236  EngngModel *rve = this->giveDomain()->giveEngngModel();
238  std :: unique_ptr< SparseLinearSystemNM >solver( classFactory.createSparseLinSolver( ST_Petsc, this->domain, this->domain->giveEngngModel() ) ); // = rve->giveLinearSolver();
239  SparseMtrxType stype = solver->giveRecommendedMatrix(true);
242 
243  // Set up and assemble tangent FE-matrix which will make up the sensitivity analysis for the macroscopic material tangent.
244  std :: unique_ptr< SparseMtrx >Kff( classFactory.createSparseMtrx(stype) );
245  //std :: unique_ptr< SparseMtrx >Kfp( classFactory.createSparseMtrx(stype) );
246  std :: unique_ptr< SparseMtrx >Kpf( classFactory.createSparseMtrx(stype) );
247  std :: unique_ptr< SparseMtrx >Kpp( classFactory.createSparseMtrx(stype) );
248  if ( !Kff ) {
249  OOFEM_ERROR("Couldn't create sparse matrix of type %d\n", stype);
250  }
251  Kff->buildInternalStructure(rve, 1, fnum);
252  //Kfp->buildInternalStructure(rve, 1, fnum, pnum);
253  Kpf->buildInternalStructure(rve, 1, pnum, fnum);
254  Kpp->buildInternalStructure(rve, 1, pnum);
255 
256  Timer t;
257  t.startTimer();
258 #if 0
259  rve->assemble(*Kff, tStep, TangentAssembler(TangentStiffness), fnum, this->domain);
260  //rve->assemble(*Kfp, tStep, TangentAssembler(TangentStiffness), fnum, pnum, this->domain);
261  rve->assemble(*Kpf, tStep, TangentAssembler(TangentStiffness), pnum, fnum, this->domain);
262  rve->assemble(*Kpp, tStep, TangentAssembler(TangentStiffness), pnum, this->domain);
263 #else
264  auto ma = TangentAssembler(TangentStiffness);
265  IntArray floc, ploc;
266  FloatMatrix mat, R;
267 
268  int nelem = domain->giveNumberOfElements();
269 #ifdef _OPENMP
270  #pragma omp parallel for shared(Kff, Kpf, Kpp) private(mat, R, floc, ploc)
271 #endif
272  for ( int ielem = 1; ielem <= nelem; ielem++ ) {
273  Element *element = domain->giveElement(ielem);
274  // skip remote elements (these are used as mirrors of remote elements on other domains
275  // when nonlocal constitutive models are used. They introduction is necessary to
276  // allow local averaging on domains without fine grain communication between domains).
277  if ( element->giveParallelMode() == Element_remote || !element->isActivated(tStep) ) {
278  continue;
279  }
280 
281  ma.matrixFromElement(mat, *element, tStep);
282 
283  if ( mat.isNotEmpty() ) {
284  ma.locationFromElement(floc, *element, fnum);
285  ma.locationFromElement(ploc, *element, pnum);
287  if ( element->giveRotationMatrix(R) ) {
288  mat.rotatedWith(R);
289  }
290 
291 #ifdef _OPENMP
292  #pragma omp critical
293 #endif
294  {
295  Kff->assemble(floc, mat);
296  Kpf->assemble(ploc, floc, mat);
297  Kpp->assemble(ploc, mat);
298  }
299  }
300  }
301  Kff->assembleBegin();
302  Kpf->assembleBegin();
303  Kpp->assembleBegin();
304 
305  Kff->assembleEnd();
306  Kpf->assembleEnd();
307  Kpp->assembleEnd();
308 #endif
309  t.stopTimer();
310  OOFEM_LOG_INFO("Assembly time %.3f s\n", t.getUtime());
311 
312  FloatMatrix C, X, Kpfa, KfpC, sol;
313 
314  this->computeCoefficientMatrix(C);
315  Kpf->timesT(C, KfpC);
316 
317  // Initial guess (Taylor assumption) helps KSP-iterations
318  sol.resize(KfpC.giveNumberOfRows(), KfpC.giveNumberOfColumns());
320  for ( auto &n : domain->giveDofManagers() ) {
321  int k1 = n->giveDofWithID( this->dofs(0) )->__giveEquationNumber();
322  if ( k1 ) {
323  FloatArray *coords = n->giveCoordinates();
324  for ( int i = 1; i <= nsd; ++i ) {
325  sol.at(k1, i) = -(coords->at(i) - mCenterCoord.at(i));
326  }
327  }
328  }
329 
330  t.startTimer();
331  if ( solver->solve(*Kff, KfpC, sol) & NM_NoSuccess ) {
332  OOFEM_ERROR("Failed to solve Kff");
333  }
334  t.stopTimer();
335  Kpp->times(C, X);
336  Kpf->times(sol, Kpfa);
337  X.subtract(Kpfa);
338  tangent.beTProductOf(C, X);
339  tangent.times( 1. / this->domainSize() );
340  OOFEM_LOG_INFO("Tangent problem solve time %.3f s\n", t.getUtime());
341 }
342 
344 {
346 
347  std :: unique_ptr< SparseLinearSystemNM > solver( classFactory.createSparseLinSolver(ST_Petsc, this->giveDomain(), this->giveDomain()->giveEngngModel()) );
348 
349  // One "xi" per node on the boundary. Initially all to zero.
350  this->xis.clear();
351  for ( int node : domain->giveSet(this->giveSetNumber())->giveNodeList() ) {
352  this->xis.emplace(node, FloatArray(3));
353  }
354  for ( auto &surf : this->surfSets ) {
355  for ( int node : domain->giveSet(surf)->giveNodeList() ) {
356  this->xis.emplace(node, FloatArray(3));
357  }
358  }
359 
360  OOFEM_LOG_INFO("Computing edge sets from surfaces\n");
361  // Instead of requiring the input file to specify the edges, this code will automatically detect them
362  std :: vector< std :: vector< int > > surf2edges = {{1, 2, 3, 4},
363  {9, 10, 11, 12},
364  {1, 5, 6, 9},
365  {2, 6, 7, 10},
366  {3, 7, 8, 11},
367  {4, 5, 8, 12}};
368 
369  // Edge sets generated from surface sets:
370  // 1-2, 1-3, 1-4, .. 2-3, 2-4, ..., 5-6 (skipping the empty sets)
371  // In case we ever want to use more arbitrary RVE "cutouts", this could be used.
372  std :: vector< Set > edgeSets;
373  std :: vector< std :: vector< std :: tuple< int, int > > > surfedges( this->surfSets.giveSize() );
374  for ( int i = 0; i < this->surfSets.giveSize(); ++i ) {
375  const IntArray &surfs = this->giveDomain()->giveSet(surfSets[i])->giveBoundaryList();
376  surfedges[i].reserve( 4 * surfs.giveSize() / 2 );
377  for ( int pos = 0; pos < surfs.giveSize() / 2; ++pos ) {
378  for ( int edgenum : surf2edges[surfs[pos * 2 + 1]-1] ) {
379  surfedges[i].emplace_back( std :: make_tuple(surfs[pos * 2], edgenum) );
380  }
381  }
382  }
383 
384  for ( int i = 0; i < this->surfSets.giveSize() - 1; ++i ) {
385  for ( int j = i+1; j < this->surfSets.giveSize(); ++j ) {
386  std :: vector< std :: tuple< int, int > > ijEdgeSet;
387  std :: set_intersection(surfedges[i].begin(), surfedges[i].end(),
388  surfedges[j].begin(), surfedges[j].end(), std::back_inserter(ijEdgeSet));
389  IntArray edgelist;
390  edgelist.preallocate(ijEdgeSet.size() * 2);
391  for ( auto &edge : ijEdgeSet ) {
392  edgelist.followedBy( std :: get<0>(edge) );
393  edgelist.followedBy( std :: get<1>(edge) );
394  }
395 
396  if ( edgelist.giveSize() > 0 ) {
397  Set s(0, this->giveDomain());
398  s.setEdgeList(edgelist);
399  edgeSets.emplace_back(std :: move(s));
400  }
401  }
402  }
403  // END OF EDGE-SET GENERATION
404 
405  // Identify corner nodes and all the total edge nodes (needed for equation numbering)
406  IntArray totalCornerNodes;
407  IntArray totalEdgeNodes;
408  for ( auto &setPointer : edgeSets ) {
409  const IntArray &nodes = setPointer.giveNodeList();
410  for ( int n : nodes ) {
411  if ( !totalEdgeNodes.insertSortedOnce(n, 10) ) {
412  totalCornerNodes.insertSortedOnce(n);
413  }
414  }
415  }
416 
417 #if 1
418  //IntArray edgeOrder{2, 1, 2, 1, 3, 3, 3, 3, 2, 1, 2, 1};
419  // First we must determine the values along the edges, which become boundary conditions for the surfaces
420  OOFEM_LOG_INFO("Computing xi on edges\n");
421  for ( auto &setPointer : edgeSets ) {
422  const IntArray &edges = setPointer.giveEdgeList();
423 
424  // Number the equations along this edge set
425  std :: map< int, int > eqs;
426  int eq_count = 0;
427  for ( int n : setPointer.giveNodeList() ) {
428  if ( totalCornerNodes.containsSorted(n) ) {
429  eqs[n] = 0;
430  } else {
431  eqs[n] = ++eq_count;
432  }
433  }
434 
435  FloatMatrix f;
436  FloatArray q;
438  std :: unique_ptr< SparseMtrx > K( classFactory.createSparseMtrx(solver->giveRecommendedMatrix(true)) );
439  K->buildInternalStructure(domain->giveEngngModel(), eq_count, eq_count, {}, {});
440  f.resize(eq_count, 3);
441 
442  K->assembleBegin();
443  for ( int pos = 0; pos < edges.giveSize() / 2; ++pos ) {
444  Element *e = this->giveDomain()->giveElement( edges[pos * 2] );
445  int edge = edges[pos * 2 + 1];
446 
447  FloatMatrix D, Ke, fe;
448  FloatArray b;
449 
450  FEInterpolation3d *interp = static_cast< FEInterpolation3d* >( e->giveInterpolation() );
451  IntArray bNodes;
452  interp->boundaryEdgeGiveNodes(bNodes, edge);
453  int order = interp->giveInterpolationOrder();
454  std :: unique_ptr< IntegrationRule > ir( interp->giveBoundaryEdgeIntegrationRule(order, edge) );
455  static_cast< TransportElement* >(e)->computeConstitutiveMatrixAt(D, Capacity, e->giveDefaultIntegrationRulePtr()->getIntegrationPoint(1), tStep);
456 
457  // Compute integral of B'*D*B and N:
458  for ( auto &gp: *ir ) {
459  const FloatArray &lcoords = gp->giveNaturalCoordinates();
460  FEIElementGeometryWrapper cellgeo(e);
461 
462  double detJ = interp->boundaryEdgeGiveTransformationJacobian(edge, lcoords, cellgeo);
463  interp->edgeEvaldNdxi(b, edge, lcoords, cellgeo);
464  b.times(1. / detJ);
465  double dL = detJ * gp->giveWeight();
466 
467  // Compute material property
469  //static_cast< TransportElement* >(e)->computeConstitutiveMatrixAt(D, Capacity, gp, tStep);
470 #if 1
471  FloatArray t;
472  for ( int i = 1; i <= b.giveSize(); ++i ) {
473  t.add(b.at(i), *e->giveNode(bNodes.at(i))->giveCoordinates());
474  }
475  t.normalize();
476  FloatArray tmp;
477  tmp.beProductOf(D, t);
478  double k = tmp.dotProduct(t);
479 #else
480  double k = D.at(1,1);
481 #endif
482 
483  Ke.plusDyadSymmUpper(b, k * dL);
484  }
485  Ke.symmetrized();
486 
487  // Need the element-nodal coordinates for the RHS, as the associated location array:
488  IntArray loc(bNodes.giveSize());
489  FloatMatrix cvec(bNodes.giveSize(), 3);
490  for ( int i = 1; i <= bNodes.giveSize(); ++i ) {
491  int enode = bNodes.at(i);
492  Node *n = e->giveNode(enode);
493  const FloatArray &x = *n->giveCoordinates();
494  cvec.at(i, 1) = x.at(1);
495  cvec.at(i, 2) = x.at(2);
496  cvec.at(i, 3) = x.at(3);
497  loc.at(i) = eqs[n->giveNumber()];
498  }
499 
500  fe.beProductOf(Ke, cvec);
501  fe.negated();
502  f.assemble(fe, loc, {1, 2, 3});
503  K->assemble(loc, Ke);
504  }
505  K->assembleEnd();
506 
507  FloatMatrix x;
508  solver->solve(*K, f, x);
509 
510  for ( int n : setPointer.giveNodeList() ) {
511  int eq = eqs[n];
512  if ( eq > 0 ) {
513  this->xis[n] = {x.at(eq, 1), x.at(eq, 2), x.at(eq, 3)};
514  }
515  }
516  }
517 #endif
518 
519  OOFEM_LOG_INFO("Computing xi on surface sets\n");
520 #if 1
521  // Surfaces use the edge solutions are boundary conditions:
522  for ( auto &setNum : surfSets ) {
523  Set *setPointer = this->giveDomain()->giveSet(setNum);
524  const IntArray &surfs = setPointer->giveBoundaryList();
525 
526  // Number the equations along this surface set
527  std :: map< int, int > eqs;
528  int eq_count = 0;
529  for ( int n : setPointer->giveNodeList() ) {
530  if ( totalEdgeNodes.containsSorted(n) ) {
531  eqs[n] = 0;
532  } else {
533  eqs[n] = ++eq_count;
534  }
535  }
536 
537  FloatMatrix f;
539  FloatArray q;
540  std :: unique_ptr< SparseMtrx > K( classFactory.createSparseMtrx(solver->giveRecommendedMatrix(true)) );
541  K->buildInternalStructure(domain->giveEngngModel(), eq_count, eq_count, {}, {});
542  f.resize(eq_count, 3);
543  q.resize(eq_count);
544 
545  K->assembleBegin();
547  for ( int pos = 0; pos < surfs.giveSize() / 2; ++pos ) {
548  Element *e = this->giveDomain()->giveElement( surfs[pos * 2] );
549  int surf = surfs[pos * 2 + 1];
550 
551  FloatMatrix D, B, dNdx, DB, Ke, fe;
552  FloatArray n, qe, normal;
553 
554  FEInterpolation3d *interp = static_cast< FEInterpolation3d* >( e->giveInterpolation() );
555  int order = interp->giveInterpolationOrder();
556  std :: unique_ptr< IntegrationRule > ir( interp->giveBoundaryIntegrationRule(order, surf) );
557  static_cast< TransportElement* >(e)->computeConstitutiveMatrixAt(D, Capacity, e->giveDefaultIntegrationRulePtr()->getIntegrationPoint(1), tStep);
558 
559  for ( auto &gp: *ir ) {
560  const FloatArray &lcoords = gp->giveNaturalCoordinates();
561  FEIElementGeometryWrapper cellgeo(e);
562 
563  interp->boundaryEvalN(n, surf, lcoords, cellgeo);
564 
565  double detJ = interp->boundaryEvalNormal(normal, surf, lcoords, cellgeo);
566  interp->surfaceEvaldNdx(dNdx, surf, lcoords, cellgeo);
567  B.beTranspositionOf(dNdx);
568  double dA = detJ * gp->giveWeight();
569 
570  for (int i = 1; i <= B.giveNumberOfRows(); ++i ) {
571  for (int j = 1; j <= B.giveNumberOfColumns(); ++j ) {
572  double tmp = 0;
573  for (int k = 1; k <= 3; ++k ) {
574  tmp += normal.at(k) * B.at(k,j);
575  }
576  B.at(i,j) -= normal.at(i) * tmp;
577  }
578  }
579 
580  // Compute material property
582  //static_cast< TransportElement* >(e)->computeConstitutiveMatrixAt(D, Capacity, gp, tStep);
583 
584  // Vector:
585  DB.beProductOf(D, B);
586  Ke.plusProductSymmUpper(B, DB, dA);
587  qe.add(dA, n);
588  }
589  Ke.symmetrized();
590 
591  IntArray bNodes;
592  interp->boundaryGiveNodes(bNodes, surf);
593  IntArray loc(bNodes.giveSize());
594  FloatMatrix cvec(bNodes.giveSize(), 3);
595  for ( int i = 1; i <= bNodes.giveSize(); ++i ) {
596  int enode = bNodes.at(i);
597  Node *n = e->giveNode(enode);
598  FloatArray x = *n->giveCoordinates() + this->xis[n->giveNumber()];
599  cvec.at(i, 1) = x.at(1);
600  cvec.at(i, 2) = x.at(2);
601  cvec.at(i, 3) = x.at(3);
602  loc.at(i) = eqs[n->giveNumber()];
603  }
604  fe.beProductOf(Ke, cvec);
605  fe.negated();
606 
607  K->assemble(loc, Ke);
608  f.assemble(fe, loc, {1, 2, 3});
609  q.assemble(qe, loc);
610  }
611  K->assembleEnd();
612 
613  // Solve with constraints:
614  // [K Q] [xi ] = [f]
615  // [Q^T 0] [lambda ] [0]
616  // ==>
617  // [Q^T . K^(-1) . Q] . lamda = Q^T . K^(-1) . f
618  // xi = K^(-1) . f - K^(-1) . Q . lambda
619  // alternatively:
620  // [Q^T . Qx] . lamda = Q^T . fx
621  // xi = fx - Qx . lambda
622 
623  double qTKiq;
624  FloatMatrix x;
625  FloatArray qx, lambda, tmp, qTKif;
626  solver->solve(*K, q, qx);
627  solver->solve(*K, f, x);
628 
629  qTKif.beTProductOf(x, q);
630  qTKiq = q.dotProduct(qx);
631  lambda.beScaled(1./qTKiq, qTKif);
632  x.plusDyadUnsym(qx, lambda, -1.0);
633 
634  for ( int n : setPointer->giveNodeList() ) {
635  int eq = eqs[n];
636  if ( eq > 0 ) {
637  this->xis[n] = {x.at(eq, 1), x.at(eq, 2), x.at(eq, 3)};
638  }
639  }
640 
641  }
642 #endif
643 }
644 
645 } // end namespace oofem
void setField(int item, InputFieldType id)
virtual bool isActivated(TimeStep *tStep)
Definition: element.C:793
int giveNumberOfColumns() const
Returns number of columns of receiver.
Definition: floatmatrix.h:158
The representation of EngngModel default unknown numbering.
virtual void boundaryEdgeGiveNodes(IntArray &answer, int boundary)
Gives the boundary nodes for requested boundary number.
Definition: feinterpol3d.C:46
REGISTER_BoundaryCondition(BoundaryCondition)
virtual double evaluateAccelerationAtTime(double t)=0
Returns the second time derivative of the function at given time.
Class and object Domain.
Definition: domain.h:115
virtual IntegrationRule * giveDefaultIntegrationRulePtr()
Access method for default integration rule.
Definition: element.h:822
Implementation for assembling internal forces vectors in standard monolithic, nonlinear FE-problems...
virtual int giveNumberOfDomainEquations(int di, const UnknownNumberingScheme &num)
Returns number of equations for given domain in active (current time step) time step.
Definition: engngm.C:391
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition: femcmpnn.h:82
virtual double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
Evaluates the normal on the requested boundary.
Definition: feinterpol3d.C:76
SparseMtrx * createSparseMtrx(SparseMtrxType type)
Creates new instance of sparse matrix corresponding to given keyword.
Definition: classfactory.C:105
const IntArray & giveBoundaryList()
Returns list of element boundaries within set.
Definition: set.C:140
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
ValueModeType
Type representing the mode of UnknownType or CharType, or similar types.
Definition: valuemodetype.h:78
int giveInterpolationOrder()
Returns the interpolation order.
Definition: feinterpol.h:159
bool insertSortedOnce(int value, int allocChunk=0)
Inserts given value into a receiver, which is assumed to be sorted.
Definition: intarray.C:360
virtual FloatArray * giveCoordinates()
Definition: dofmanager.h:382
EngngModel * giveEngngModel()
Returns engineering model to which receiver is associated.
Definition: domain.C:433
Implementation for assembling tangent matrices in standard monolithic FE-problems.
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
Abstract base class for all finite elements.
Definition: element.h:145
std::vector< std::unique_ptr< DofManager > > & giveDofManagers()
Definition: domain.h:400
void negated()
Changes sign of receiver values.
Definition: floatmatrix.C:1605
int giveNumber()
Returns domain number.
Definition: domain.h:266
int giveNumberOfElements() const
Returns number of elements in domain.
Definition: domain.h:434
virtual double evalNXIntegral(int boundary, const FEICellGeometry &cellgeo)
Computes the integral .
Definition: feinterpol.h:420
void plusDyadUnsym(const FloatArray &a, const FloatArray &b, double dV)
Adds to the receiver the product .
Definition: floatmatrix.C:811
int giveNumberOfSpatialDimensions()
Returns number of spatial dimensions.
Definition: domain.C:1067
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
virtual int __givePrescribedEquationNumber()=0
Returns prescribed equation number of receiver.
virtual FEInterpolation * giveInterpolation() const
Definition: element.h:629
virtual void edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
Evaluates the matrix of derivatives of edge interpolation functions (shape functions) at given point...
Definition: feinterpol3d.C:123
virtual IntegrationRule * giveBoundaryIntegrationRule(int order, int boundary)
Sets up a suitable integration rule for integrating over the requested boundary.
Definition: feinterpol3d.h:195
void beDifferenceOf(const FloatArray &a, const FloatArray &b)
Sets receiver to be a - b.
Definition: floatarray.C:341
#define NM_NoSuccess
Numerical method failed to solve problem.
Definition: nmstatus.h:48
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes receiver according to object description stored in input record.
Class representing a general abstraction for finite element interpolation class.
Definition: feinterpol.h:132
bool isNotEmpty() const
Tests for empty matrix.
Definition: floatmatrix.h:162
virtual void assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAssembler &ma, const UnknownNumberingScheme &s, Domain *domain)
Assembles characteristic matrix of required type into given sparse matrix.
Definition: engngm.C:803
void beScaled(double s, const FloatArray &b)
Sets receiver to be .
Definition: floatarray.C:146
virtual void computeTangent(FloatMatrix &tangent, TimeStep *tStep)
Computes the macroscopic tangent for homogenization problems through sensitivity analysis.
#define OOFEM_LOG_INFO(...)
Definition: logger.h:127
Element * giveElement(int n)
Service for accessing particular domain fe element.
Definition: domain.C:160
double dotProduct(const FloatArray &x) const
Computes the dot product (or inner product) of receiver and argument.
Definition: floatarray.C:463
virtual void boundaryGiveNodes(IntArray &answer, int boundary)
Gives the boundary nodes for requested boundary number.
Definition: feinterpol3d.C:66
std::map< int, FloatArray > xis
Stores one "psi" value for each node.
#define _IFT_TransportGradientDirichlet_gradient
virtual void computeField(FloatArray &sigma, TimeStep *tStep)
Computes the homogenized, macroscopic, field (stress).
#define OOFEM_ERROR(...)
Definition: error.h:61
virtual double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
Evaluates the determinant of the transformation Jacobian on the requested boundary.
Definition: feinterpol3d.C:56
void setEdgeList(IntArray newEdges)
Sets list of element edges within set (must be edges of 3D elements).
Definition: set.C:208
SparseMtrxType
Enumerative type used to identify the sparse matrix type.
Implementation for assembling external forces vectors in standard monolithic FE-problems.
void times(double f)
Multiplies receiver by factor f.
Definition: floatmatrix.C:1594
This abstract class represent a general base element class for transport problems.
Set of elements, boundaries, edges and/or nodes.
Definition: set.h:66
void computeXi()
Computes the offset values for "improved" Dirichlet. See class description.
void rotatedWith(const FloatMatrix &r, char mode= 'n')
Returns the receiver &#39;a&#39; transformed using give transformation matrix r.
Definition: floatmatrix.C:1557
virtual double give(Dof *dof, ValueModeType mode, double time)
const IntArray & giveNodeList()
Returns list of all nodes within set.
Definition: set.C:146
Wrapper around element definition to provide FEICellGeometry interface.
Definition: feinterpol.h:95
Set * giveSet(int n)
Service for accessing particular domain set.
Definition: domain.C:363
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Receiver becomes the result of the product of aMatrix and anArray.
Definition: floatarray.C:676
virtual bool giveRotationMatrix(FloatMatrix &answer)
Transformation matrices updates rotation matrix between element-local and primary DOFs...
Definition: element.C:259
void plusProductSymmUpper(const FloatMatrix &a, const FloatMatrix &b, double dV)
Adds to the receiver the product .
Definition: floatmatrix.C:698
IntArray dofs
Dofs that b.c. is applied to (relevant for Dirichlet type b.c.s).
#define _IFT_TransportGradientDirichlet_tractionControl
void beTProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Receiver becomes the result of the product of aMatrix^T and anArray.
Definition: floatarray.C:708
double at(int i, int j) const
Coefficient access function.
Definition: floatmatrix.h:176
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes receiver according to object description stored in input record.
virtual double evaluateVelocityAtTime(double t)=0
Returns the first time derivative of the function at given time.
virtual void postInitialize()
Performs post initialization steps.
Class representing vector of real numbers.
Definition: floatarray.h:82
void plusDyadSymmUpper(const FloatArray &a, double dV)
Adds to the receiver the dyadic product .
Definition: floatmatrix.C:756
SparseLinearSystemNM * createSparseLinSolver(LinSystSolverType st, Domain *d, EngngModel *m)
Creates new instance of SparseLinearSystemNM corresponding to given type.
Definition: classfactory.C:120
elementParallelMode giveParallelMode() const
Return elementParallelMode of receiver.
Definition: element.h:1069
virtual void postInitialize()
Performs post initialization steps.
Implementation of matrix containing floating point numbers.
Definition: floatmatrix.h:94
IRResultType
Type defining the return values of InputRecord reading operations.
Definition: irresulttype.h:47
GaussPoint * getIntegrationPoint(int n)
Access particular integration point of receiver.
virtual void surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
Evaluates the matrix of derivatives of edge interpolation functions (shape functions) at given point...
Definition: feinterpol3d.C:128
void assemble(const FloatArray &fe, const IntArray &loc)
Assembles the array fe (typically, the load vector of a finite element) into the receiver, using loc as location array.
Definition: floatarray.C:551
void resize(int rows, int cols)
Checks size of receiver towards requested bounds.
Definition: floatmatrix.C:1358
Class representing the general Input Record.
Definition: inputrecord.h:101
The representation of EngngModel default prescribed unknown numbering.
Class representing a general abstraction for surface finite element interpolation class...
Definition: feinterpol3d.h:44
void followedBy(const IntArray &b, int allocChunk=0)
Appends array b at the end of receiver.
Definition: intarray.C:145
void zero()
Zeroes all coefficients of receiver.
Definition: floatarray.C:658
Class implementing single timer, providing wall clock and user time capabilities. ...
Definition: timer.h:46
void beTProductOf(const FloatMatrix &a, const FloatMatrix &b)
Assigns to the receiver product of .
Definition: floatmatrix.C:367
#define _IFT_TransportGradientDirichlet_surfSets
#define _IFT_TransportGradientDirichlet_centerCoords
virtual void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo)
Evaluates the basis functions on the requested boundary.
Definition: feinterpol3d.C:71
Class representing the a dynamic Input Record.
void times(double s)
Multiplies receiver with scalar.
Definition: floatarray.C:818
void beTranspositionOf(const FloatMatrix &src)
Assigns to the receiver the transposition of parameter.
Definition: floatmatrix.C:323
ClassFactory & classFactory
Definition: classfactory.C:59
Element in active domain is only mirror of some remote element.
Definition: element.h:102
virtual FloatArray * giveCoordinates()
Definition: node.h:114
void zero()
Zeroes all coefficient of receiver.
Definition: floatmatrix.C:1326
Domain * giveDomain() const
Definition: femcmpnn.h:100
virtual void giveInputRecord(DynamicInputRecord &input)
Setups the input record string of receiver.
Abstract base class representing the "problem" under consideration.
Definition: engngm.h:181
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:78
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
Assigns to the receiver product of .
Definition: floatmatrix.C:337
DofManager * giveDofManager() const
Definition: dof.h:123
virtual TimeStep * giveCurrentStep(bool force=false)
Returns current time step.
Definition: engngm.h:683
int giveSize() const
Definition: intarray.h:203
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
void preallocate(int futureSize)
Preallocates receiver to given futureSize if larger then allocatedSize.
Definition: intarray.C:130
the oofem namespace is to define a context or scope in which all oofem names are defined.
void assemble(const FloatMatrix &src, const IntArray &loc)
Assembles the contribution using localization array into receiver.
Definition: floatmatrix.C:251
Class implementing node in finite element mesh.
Definition: node.h:87
#define IR_GIVE_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:69
Abstract class Dof represents Degree Of Freedom in finite element mesh.
Definition: dof.h:93
int giveNumber() const
Definition: femcmpnn.h:107
bool containsSorted(int value) const
Checks if sorted receiver contains a given value.
Definition: intarray.h:238
void computeCoefficientMatrix(FloatMatrix &C)
Constructs a coefficient matrix for all prescribed unknowns.
virtual void giveInputRecord(DynamicInputRecord &input)
Setups the input record string of receiver.
double normalize()
Normalizes receiver.
Definition: floatarray.C:828
Node * giveNode(int i) const
Returns reference to the i-th node of element.
Definition: element.h:610
int giveNumberOfRows() const
Returns number of rows of receiver.
Definition: floatmatrix.h:156
void symmetrized()
Initializes the lower half of the receiver according to the upper half.
Definition: floatmatrix.C:1576
void startTimer()
Definition: timer.C:69
virtual double evaluateAtTime(double t)
Returns the value of the function at given time.
Definition: function.C:76
double getUtime()
Returns total user time elapsed in seconds.
Definition: timer.C:105
virtual IntegrationRule * giveBoundaryEdgeIntegrationRule(int order, int boundary)
Sets up a suitable integration rule for integrating over the requested boundary.
Definition: feinterpol3d.C:115
void assembleVector(FloatArray &answer, TimeStep *tStep, const VectorAssembler &va, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms=NULL)
Assembles characteristic vector of required type from dofManagers, element, and active boundary condi...
Definition: engngm.C:986
Class representing solution step.
Definition: timestep.h:80
void stopTimer()
Definition: timer.C:77
void add(const FloatArray &src)
Adds array src to receiver.
Definition: floatarray.C:156
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:32 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011