OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
weakperiodicbc.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 
35 #include <cstdio>
36 #include <cstdlib>
37 #include <algorithm>
38 #include <memory>
39 
40 #include "activebc.h"
41 #include "weakperiodicbc.h"
42 #include "inputrecord.h"
43 #include "element.h"
44 #include "node.h"
45 #include "masterdof.h"
46 #include "sparsemtrx.h"
47 #include "gausspoint.h"
48 #include "integrationrule.h"
49 #include "mathfem.h"
50 #include "fei2dtrlin.h"
51 #include "fei2dtrquad.h"
52 #include "classfactory.h"
53 #include "set.h"
54 #include "function.h"
55 
56 #include "timestep.h"
57 // #include "../sm/Elements/tet21ghostsolid.h"
58 #include "../sm/Elements/nlstructuralelement.h"
59 
60 namespace oofem {
61 REGISTER_BoundaryCondition(WeakPeriodicBoundaryCondition);
62 
64 {
66  doUpdateSminmax = true;
67 }
68 
70 {
71 }
72 
75 {
76  IRResultType result;
77 
79  if ( result != IRRT_OK ) {
80  return result;
81  }
82 
83  orderOfPolygon = 2;
85 
86  int t = ( int ) monomial;
88  useBasisType = ( basisType ) t; // Fourierseries by default
89 
90  //dofids = P_f; // Pressure as default
93 
94  ngp = -1; // Pressure as default
96  if ( ngp != -1 ) {
97  OOFEM_WARNING("ngp isn't being used anymore! see how the interpolator constructs the integration rule automatically.");
98  return IRRT_BAD_FORMAT;
99  }
100 
101 
102  nlgeo = false;
104 
105 
107  g.zero();
109 
110  IntArray temp;
111 
112  posSet = -1;
113  negSet = -1;
114 
117 
118  if ( posSet == -1 ) {
120  for ( int i = 0; i < temp.giveSize() / 2; i++ ) {
121  side [ 0 ].push_back( temp.at(2 * i + 1) );
122  element [ 0 ].push_back( temp.at(2 * i + 2) );
123  }
124  }
125 
126  if ( negSet == -1 ) {
128  for ( int i = 0; i < temp.giveSize() / 2; i++ ) {
129  side [ 1 ].push_back( temp.at(2 * i + 1) );
130  element [ 1 ].push_back( temp.at(2 * i + 2) );
131  }
132  }
133 
134  if ( this->domain->giveNumberOfSpatialDimensions() == 2 ) {
135  ndof = (orderOfPolygon + 1) * dofids.giveSize();
136  tcount = (orderOfPolygon + 1);
137  } else if ( this->domain->giveNumberOfSpatialDimensions() == 3 ) {
138  ndof = 1;
139  for ( int i = 1; i <= orderOfPolygon; i++ ) {
140  ndof = ndof + ( i + 1 );
141  }
142  tcount = ndof;
143  ndof = ndof * ndofids;
144  }
145 
146  // Create dofs for coefficients
147  bcID = this->giveNumber();
148  gamma_ids.clear();
149  for ( int i = 0; i < ndof; i++ ) {
150  int dofid = this->domain->giveNextFreeDofID();
151  gamma_ids.followedBy(dofid);
152  gammaDman->appendDof( new MasterDof( gammaDman.get(), ( DofIDItem )dofid ) );
153  }
154 
155  return IRRT_OK;
156 }
157 
159 {
160  /* gsMatrix contains the coefficients for the orthogonal basis. The row represents the basis and the column the coefficients. */
162  gsMatrix.zero();
163  gsMatrix.at(1, 1) = 1;
164 
165  for ( int i = 2; i <= ndof; i++ ) { // Need ndof base functions. i indicates the row of gsMatrix, ie which polynomial is the current.
166  gsMatrix.at(i, i) = 1; // Copy from V
167 
168  // remove projection of v_i on all previous base functions
169  for ( int j = 1; j < i; j++ ) {
170  FloatArray uTemp;
171  uTemp.resize(ndof);
172 
173  for ( int k = 1; k <= ndof; uTemp.at(k) = gsMatrix.at(j, k), k++ ) {
174  ;
175  }
176 
177  double thisValue = computeProjectionCoefficient(i, j);
178  uTemp.times(-thisValue);
179 
180  for ( int k = 1; k <= ndof; gsMatrix.at(i, k) = gsMatrix.at(i, k) + uTemp.at(k), k++ ) {
181  ;
182  }
183 
184  }
185  }
186 }
187 
189 {
190  /* Computes <v, u>/<u, u> where vIndex is the term in the polynomial and uIndex is the number of the base v being projected on. */
191  int thisSide = 0;
192 
193  double value = 0.0, nom = 0.0, denom = 0.0;
194 
195  int A, B, thisOrder;
196  getExponents(vIndex, A, B);
197  thisOrder = A + B;
198  getExponents(uIndex, A, B);
199  thisOrder = thisOrder + A + B;
200 
201  // Loop over all elements
202  for ( size_t ielement = 0; ielement < element [ thisSide ].size(); ielement++ ) {
203  // Compute <v, u_i>/<u_i, u_i> on this element and store in nom/denom
204 
205  Element *thisElement = this->domain->giveElement( element [ thisSide ].at(ielement) );
206  FEInterpolation *geoInterpolation = thisElement->giveInterpolation();
207 
208  std :: unique_ptr< IntegrationRule >iRule(geoInterpolation->giveBoundaryIntegrationRule(thisOrder, side [ thisSide ].at(ielement)));
209 
210  for ( GaussPoint *gp: *iRule ) {
211 
212  const FloatArray &lcoords = gp->giveNaturalCoordinates();
213  FloatArray gcoords;
214 
215  geoInterpolation->boundaryLocal2Global( gcoords, side [ thisSide ].at(ielement), lcoords, FEIElementGeometryWrapper(thisElement) );
216  double detJ = fabs( geoInterpolation->boundaryGiveTransformationJacobian( side [ thisSide ].at(ielement), lcoords, FEIElementGeometryWrapper(thisElement) ) );
217 
218  int a, b;
219  getExponents(vIndex, a, b);
220  double vVal = pow(gcoords.at( surfaceIndexes.at(1) ), a) * pow(gcoords.at( surfaceIndexes.at(2) ), b);
221 
222  double uValue = 0.0;
223  for ( int k = 1; k < ndof; k++ ) {
224  int c, d;
225  getExponents(k, c, d);
226  uValue = uValue + gsMatrix.at(uIndex, k) * pow(gcoords.at( surfaceIndexes.at(1) ), c) * pow(gcoords.at( surfaceIndexes.at(2) ), d);
227  }
228 
229  nom = nom + vVal *uValue *detJ *gp->giveWeight();
230  denom = denom + uValue *uValue *detJ *gp->giveWeight();
231  }
232  }
233 
234  value = nom / denom;
235 
236  return value;
237 }
238 
240 {
241  FloatArray xi;
242 
243  if ( this->domain->giveNumberOfSpatialDimensions() == 3 ) {
244  xi.resize(2);
245  xi(0) = 0.25;
246  xi(1) = 0.25;
247  } else {
248  xi.resize(1);
249  xi(0) = 0.5;
250  }
251 
252  Element *thisElement = this->domain->giveElement(element);
253  FEInterpolation *interpolation = thisElement->giveInterpolation( ( DofIDItem ) dofids(0) );
254 
255  interpolation->boundaryEvalNormal( answer, side, xi, FEIElementGeometryWrapper(thisElement) );
256 }
257 
259 {
260  // Check orientation for s
261  FloatArray normal;
262 
263  if ( this->domain->giveNumberOfSpatialDimensions() == 2 ) {
265  smin.resize(1);
266  smax.resize(1);
267  } else {
269  smin.resize(2);
270  smax.resize(2);
271  }
272 
273  giveEdgeNormal( normal, element [ 0 ].at(0), side [ 0 ].at(0) );
274 
275  if ( fabs( normal.at(1) ) > 0.99999 ) { // Normal points in X direction
276  direction = 1;
277  if ( this->domain->giveNumberOfSpatialDimensions() == 2 ) {
278  surfaceIndexes.at(1) = 2;
279  } else {
280  surfaceIndexes.at(1) = 2;
281  surfaceIndexes.at(2) = 3;
282  }
283  } else if ( fabs( normal.at(2) ) > 0.99999 ) { // Normal points in Y direction
284  direction = 2;
285  if ( this->domain->giveNumberOfSpatialDimensions() == 2 ) {
286  surfaceIndexes.at(1) = 1;
287  } else {
288  surfaceIndexes.at(1) = 1;
289  surfaceIndexes.at(2) = 3;
290  }
291  } else if ( fabs( normal.at(3) ) > 0.99 ) { // Normal points in Z direction
292  direction = 3;
293  if ( this->domain->giveNumberOfSpatialDimensions() == 2 ) {
294  OOFEM_ERROR("3 dimensioal normal in a 2 dimensional problem.");
295  } else {
296  surfaceIndexes.at(1) = 1;
297  surfaceIndexes.at(2) = 2;
298  }
299  } else {
300  normal.printYourself();
301  Element *thisElement = this->giveDomain()->giveElement( element [ 0 ].at(0) );
302  OOFEM_ERROR("Only surfaces with normal in x, y or z direction supported. (el=%d, side=%d) \n", thisElement->giveLabel(), side [ 0 ].at(0) );
303  }
304 }
305 
307 {
308  if ( doUpdateSminmax ) {
309  // If sets are used, now is the time to update lists of elements and sides since the sets are unknown in initializeFrom
310  if ( posSet != -1 ) {
311  IntArray posBoundary, negBoundary;
312 
313  posBoundary = this->giveDomain()->giveSet(posSet)->giveBoundaryList();
314  for ( int i = 0; i < posBoundary.giveSize() / 2; i++ ) {
315  side [ 0 ].push_back( posBoundary.at(2 * i + 2) );
316  element [ 0 ].push_back( posBoundary.at(2 * i + 1) );
317  }
318 
319  negBoundary = this->giveDomain()->giveSet(negSet)->giveBoundaryList();
320  for ( int i = 0; i < negBoundary.giveSize() / 2; i++ ) {
321  side [ 1 ].push_back( negBoundary.at(2 * i + 2) );
322  element [ 1 ].push_back( negBoundary.at(2 * i + 1) );
323  }
324  }
325 
326  // Determine which is the positive and which is the negative side
327  FloatArray normal;
328  giveEdgeNormal( normal, element [ 0 ].at(0), side [ 0 ].at(0) );
329 
330  double normalSum = -1;
331  ( this->giveDomain()->giveNumberOfSpatialDimensions() <= 2 ) ? normalSum = normal.at(1) + normal.at(2) : normalSum = normal.at(1) + normal.at(2) + normal.at(3);
332 
333  if ( normalSum > -0.000001 ) { // No support for 3D yet
334  sideSign [ 0 ] = 1;
335  sideSign [ 1 ] = -1;
336  } else {
337  sideSign [ 0 ] = -1;
338  sideSign [ 1 ] = 1;
339  }
340 
341  updateDirection();
342 
343  for ( int i = 1; i <= surfaceIndexes.giveSize(); i++ ) {
346 
347  for ( int j = 1; j <= this->domain->giveNumberOfDofManagers(); j++ ) {
348  double sValue = this->domain->giveDofManager(j)->giveCoordinate( surfaceIndexes.at(i) );
349  smin.at(i) = std :: min(smin.at(i), sValue);
350  smax.at(i) = std :: max(smax.at(i), sValue);
351  }
352  }
353  doUpdateSminmax = false;
354 
355  if ( this->useBasisType == legendre ) {
357  }
358  }
359 }
360 
361 void WeakPeriodicBoundaryCondition :: addElementSide(int newElement, int newSide)
362 {
363 
364  FloatArray normalNew, normal0;
365  int addToList = 0;
366 
367  if ( element [ 0 ].size() > 0 ) {
368  // If there are elements in the list, compare normals in order to determine which list to store them in
369  giveEdgeNormal(normalNew, newElement, newSide);
370  giveEdgeNormal( normal0, element [ 0 ].at(0), side [ 0 ].at(0) );
371  double d = sqrt( pow(normalNew.at(1) - normal0.at(1), 2) + pow(normalNew.at(2) - normal0.at(2), 2) );
372  if ( fabs(d) < 0.001 ) {
373  addToList = 0;
374  } else {
375  addToList = 1;
376  }
377  } else {
378  // Otherwise, check the normal in order to decide upon which direction the parameter runs (x or y)
379  giveEdgeNormal(normalNew, newElement, newSide);
380  if ( fabs(fabs( normalNew.at(1) ) - 1.) < 0.0001 ) { // Normal point in x direction, thus set direction to y
381  direction = 2;
382  } else {
383  direction = 1;
384  }
385  }
386 
387  element [ addToList ].push_back(newElement);
388  side [ addToList ].push_back(newSide);
389 }
390 
391 void
393 {
394 
395  FloatArray F, u;
396  FloatMatrix dNdx, BH, Fmatrix, Finv;
397  FEInterpolation *interpolation = e->giveInterpolation( ( DofIDItem ) dofids(0) );
398 
399  // Fetch displacements
400  e->computeVectorOf({1, 2, 3}, VM_Total, tStep, u);
401 
402  // Compute dNdx on boundary.
403  interpolation->evaldNdx(dNdx, *lcoord, FEIElementGeometryWrapper (e) );
404 
405  // Compute displcement gradient BH
406  BH.resize(9, dNdx.giveNumberOfRows() * 3);
407  BH.zero();
408 
409  for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) {
410  BH.at(1, 3 * i - 2) = dNdx.at(i, 1); // du/dx
411  BH.at(2, 3 * i - 1) = dNdx.at(i, 2); // dv/dy
412  BH.at(3, 3 * i - 0) = dNdx.at(i, 3); // dw/dz
413  BH.at(4, 3 * i - 1) = dNdx.at(i, 3); // dv/dz
414  BH.at(7, 3 * i - 0) = dNdx.at(i, 2); // dw/dy
415  BH.at(5, 3 * i - 2) = dNdx.at(i, 3); // du/dz
416  BH.at(8, 3 * i - 0) = dNdx.at(i, 1); // dw/dx
417  BH.at(6, 3 * i - 2) = dNdx.at(i, 2); // du/dy
418  BH.at(9, 3 * i - 1) = dNdx.at(i, 1); // dv/dx
419  }
420 
421  // Finally, compute deformation gradient F=BH*u+I
422  F.beProductOf(BH, u);
423  F.at(1)+=1.0;
424  F.at(2)+=1.0;
425  F.at(3)+=1.0;
426 
427  Fmatrix.beMatrixForm(F);
428  Finv.beInverseOf(Fmatrix);
429  answer.beTranspositionOf(Finv);
430 
431 }
432 
434 {
435 
436  OOFEM_ERROR("Function obsolete");
437 
438  FloatArray gcoords;
439  IntArray bnodes;
440 
441  FEInterpolation *geoInterpolation = e->giveInterpolation();
442 
443  // Use correct interpolation for the dofid on which the condition is applied
444  FEInterpolation *interpolation = e->giveInterpolation( ( DofIDItem ) dofids(0) );
445 
446  interpolation->boundaryGiveNodes(bnodes, boundary);
447 
448  B.resize(bnodes.giveSize(), ndof);
449  B.zero();
450 
451  std :: unique_ptr< IntegrationRule >iRule(geoInterpolation->giveBoundaryIntegrationRule(orderOfPolygon, boundary));
452 
453  for ( GaussPoint *gp: *iRule ) {
454  const FloatArray &lcoords = gp->giveNaturalCoordinates();
455 
456  FloatArray N;
457 
458  // Find the value of parameter s which is the vert/horiz distance to 0
459  geoInterpolation->boundaryLocal2Global( gcoords, boundary, lcoords, FEIElementGeometryWrapper(e) );
460 
461  FloatArray boundaryLocal;
462  interpolation->global2local( boundaryLocal, gcoords, FEIElementGeometryWrapper(e) );
463 
464 #if 0
465  FloatMatrix FinvT;
466  if (tStep->giveNumber()>0) {
467  if ( dynamic_cast <NLStructuralElement *> (e) != NULL ) { // If finite strains, compute deformation gradient
468  this->computeDeformationGradient(FinvT, e, &boundaryLocal, tStep);
469  FinvT.printYourself();
470  }
471  }
472 
473 #endif
474 
475  // Compute base function values
476  interpolation->boundaryEvalN( N, boundary, lcoords, FEIElementGeometryWrapper(e) );
477  // Compute Jacobian
478  double detJ = fabs( geoInterpolation->boundaryGiveTransformationJacobian( boundary, lcoords, FEIElementGeometryWrapper(e) ) );
479 
480  for ( int j = 0; j < B.giveNumberOfColumns(); j++ ) {
481 
482  double fVal = computeBaseFunctionValue(j, gcoords);
483 
484  for ( int k = 0; k < B.giveNumberOfRows(); k++ ) {
485  B(k, j) += N(k) * fVal * detJ * gp->giveWeight();
486  }
487  }
488  }
489 }
490 
492 {
493  if ( type != TangentStiffnessMatrix && type != StiffnessMatrix ) {
494  return;
495  }
496 
497  IntArray c_loc, r_loc;
498  gammaDman->giveLocationArray(gamma_ids, r_loc, r_s);
499  gammaDman->giveLocationArray(gamma_ids, c_loc, c_s);
500 
501  FloatMatrix B, BT;
502  int normalSign;
503 
504  updateSminmax();
505 
506  // Assemble each side
507  for ( int thisSide = 0; thisSide <= 1; thisSide++ ) {
508  normalSign = sideSign [ thisSide ];
509 
510  for ( size_t ielement = 0; ielement < element [ thisSide ].size(); ielement++ ) { // Loop over each element on this edge
511  Element *thisElement = this->domain->giveElement( element [ thisSide ].at(ielement) );
512  int boundary = side [ thisSide ].at(ielement);
513 
514  // Find dofs for this element side
515  IntArray r_sideLoc, c_sideLoc;
516 
517  // Find dofs for this element which should be periodic
518  IntArray bNodes;
519 
520  FEInterpolation *interpolation = thisElement->giveInterpolation( ( DofIDItem ) dofids(0) );
521  FEInterpolation *geoInterpolation = thisElement->giveInterpolation();
522 
523  interpolation->boundaryGiveNodes( bNodes, side [ thisSide ].at(ielement) );
524 
525  thisElement->giveBoundaryLocationArray(r_sideLoc, bNodes, dofids, r_s);
526  thisElement->giveBoundaryLocationArray(c_sideLoc, bNodes, dofids, c_s);
527 
528  B.resize(bNodes.giveSize()*ndofids, ndofids*tcount);
529  B.zero();
530 
531  std :: unique_ptr< IntegrationRule >iRule(geoInterpolation->giveBoundaryIntegrationRule(orderOfPolygon, boundary));
532 
533  for ( GaussPoint *gp: *iRule ) {
534  FloatArray lcoords = gp->giveNaturalCoordinates();
535  FloatArray N, gcoords;
536 
537  geoInterpolation->boundaryLocal2Global( gcoords, boundary, lcoords, FEIElementGeometryWrapper(thisElement));
538 
539  interpolation->boundaryEvalN(N, boundary, lcoords, FEIElementGeometryWrapper(thisElement));
540 
541  double detJ = fabs( geoInterpolation->boundaryGiveTransformationJacobian( boundary, lcoords, FEIElementGeometryWrapper(thisElement) ) );
542 
543  FloatMatrix Mbeta(ndofids, ndof), Mv(ndofids, bNodes.giveSize()*ndofids), NvTNbeta;
544 
545  for (int i=0; i<tcount; i++) {
546  for (int j=0; j<ndofids; j++) {
547  Mbeta.at(j+1, ndofids*i+j+1) = computeBaseFunctionValue(i, gcoords);
548  }
549  }
550 
551  for (int i=0; i<N.giveSize(); i++) {
552  for (int j=0; j<ndofids; j++) {
553  Mv.at(j+1, ndofids*i+j+1) = N.at(i+1);
554  }
555  }
556 
557  FloatMatrix defNv, F, Finv;
558  double J=1.0;
559 
560  if (nlgeo) {
561  FloatArray elocal;
562  geoInterpolation->global2local(elocal, gcoords, FEIElementGeometryWrapper(thisElement));
563  computeDeformationGradient(F, thisElement, &elocal, tStep);
564 // J=F.giveDeterminant();
565  Finv.beInverseOf(F);
566  defNv.beProductOf(Finv, Mv);
567  } else {
568  defNv = Mv;
569  }
570 
571  NvTNbeta.beTProductOf(defNv, Mbeta);
572 
573  NvTNbeta.times(J * detJ * gp->giveWeight());
574  B.add(NvTNbeta);
575 
576 
577 /* for (int i=0; i<ndof; i++) {
578  double fVal = computeBaseFunctionValue(i, gcoords);
579  for ( int k = 0; k < B.giveNumberOfRows(); k++ ) {
580  B(k, i) += N(k) * fVal * detJ * gp->giveWeight();
581  }
582  }*/
583 
584 
585  }
586 
587  B.times(normalSign * scale);
588  BT.beTranspositionOf(B);
589 
590  answer.assemble(r_sideLoc, c_loc, B);
591  answer.assemble(r_loc, c_sideLoc, BT);
592  }
593  }
594 
595 }
596 
597 double
599 {
600  if (this->domain->giveNumberOfSpatialDimensions() == 2) {
601  return computeBaseFunctionValue1D(baseID, coordinate.at(surfaceIndexes.at(1)));
602  } else {
603  return computeBaseFunctionValue2D(baseID, {coordinate.at(surfaceIndexes.at(1)), coordinate.at(surfaceIndexes.at(2))});
604  }
605 }
606 
608 {
609  double fVal = 0.0;
610 
611  if ( useBasisType == monomial ) {
612  int a, b;
613  getExponents(baseID+1, a, b);
614  fVal = pow(coordinate.at(1), a) * pow(coordinate.at(2), b);
615  } else if ( useBasisType == legendre ) {
616  for ( int i = 1; i <= ndof; i++ ) {
617  int a, b;
618  getExponents(i, a, b);
619  fVal = fVal + gsMatrix.at(baseID+1, i) * pow(coordinate.at(1), a) * pow(coordinate.at(2), b);
620  }
621  }
622  // printf("Value for u_%u att coordinate %f, %f is %f\n", baseID, coordinate.at(1), coordinate.at(2), fVal);
623  return fVal;
624 }
625 
627 {
628  double fVal = 0.0;
629  FloatArray sideLength;
630 
631  // compute side lengths
632  sideLength.resize( smax.giveSize() );
633  for ( int i = 1; i <= smax.giveSize(); i++ ) {
634  sideLength.at(i) = smax.at(i) - smin.at(i);
635  }
636 
637  if ( useBasisType == monomial ) {
638  fVal = pow(coordinate, baseID);
639  } else if ( useBasisType == trigonometric ) {
640  if ( baseID % 2 == 0 ) { // Even (does not yet work in 3D)
641  fVal = cos( ( ( double ) baseID ) / 2. * ( coordinate * 2. * M_PI / sideLength.at(1) ) );
642  } else {
643  fVal = sin( ( ( double ) baseID + 1 ) / 2. * ( coordinate * 2. * M_PI / sideLength.at(1) ) );
644  }
645  } else if ( useBasisType == legendre ) {
646  double n = ( double ) baseID;
647  coordinate = 2.0 * coordinate - 1.0;
648  for ( int k = 0; k <= baseID; k++ ) {
649  fVal = fVal + binomial(n, k) * binomial(-n - 1.0, k) * pow( ( 1.0 - coordinate ) / 2.0, ( double ) k );
650  }
651  }
652 
653  return fVal;
654 }
655 
657  CharType type, ValueModeType mode,
658  const UnknownNumberingScheme &s, FloatArray *eNorms)
659 {
660  if ( type == InternalForcesVector ) {
661  giveInternalForcesVector(answer, tStep, type, mode, s);
662  } else if ( type == ExternalForcesVector ) {
663  giveExternalForcesVector(answer, tStep, type, mode, s);
664  }
665 
666 }
667 
668 void
670  CharType type, ValueModeType mode,
671  const UnknownNumberingScheme &s, FloatArray *eNorms)
672 {
673  // Fetch unknowns of this boundary condition
674  IntArray gammaLoc;
675  FloatArray gamma;
676  gammaDman->giveUnknownVector(gamma, gamma_ids, mode, tStep);
677  gammaDman->giveLocationArray(gamma_ids, gammaLoc, s);
678 
679  // Values from solution
680  FloatArray a;
681  // Find dofs for this element side
682  IntArray sideLocation, masterDofIDs;
683 
684  FloatMatrix B;
685 
686  int normalSign;
687 
688  updateSminmax();
689 
690  // Assemble each side
691  for ( int thisSide = 0; thisSide <= 1; thisSide++ ) {
692  normalSign = sideSign [ thisSide ];
693 
694  for ( size_t ielement = 0; ielement < element [ thisSide ].size(); ielement++ ) { // Loop over each element on this edge
695  Element *thisElement = this->domain->giveElement( element [ thisSide ].at(ielement) );
696  int boundary = side [ thisSide ].at(ielement);
697 
698  // Find dofs for this element which should be periodic
699  IntArray bNodes;
700 
701  FEInterpolation *interpolation = thisElement->giveInterpolation( ( DofIDItem ) dofids(0) );
702  FEInterpolation *geoInterpolation = thisElement->giveInterpolation();
703 
704  interpolation->boundaryGiveNodes( bNodes, boundary );
705 
706  thisElement->giveBoundaryLocationArray(sideLocation, bNodes, dofids, s, &masterDofIDs);
707  thisElement->computeBoundaryVectorOf(bNodes, dofids, VM_Total, tStep, a);
708 
709  FloatArray vProd, gammaProd;
710 
711  B.resize(bNodes.giveSize(), ndof);
712  B.zero();
713 
714  std :: unique_ptr< IntegrationRule >iRule(geoInterpolation->giveBoundaryIntegrationRule(orderOfPolygon, boundary));
715 
716  // Where we test with velocity
717  vProd.resize(bNodes.giveSize()*dofids.giveSize());
718  vProd.zero();
719 
720  // Where we test with gamma
721  gammaProd.resize(ndof);
722  gammaProd.zero();
723 
724  // For test:
725  FloatArray myProd(gammaProd.giveSize()), myProdGamma(vProd.giveSize());
726 
727  for ( GaussPoint *gp: *iRule ) {
728  FloatArray lcoords = gp->giveNaturalCoordinates();
729  FloatArray N, gcoords;
730  FloatMatrix C, D, Nbeta, Nv;
731 
732  geoInterpolation->boundaryLocal2Global( gcoords, boundary , lcoords, FEIElementGeometryWrapper(thisElement));
733  interpolation->boundaryEvalN(N, boundary, lcoords, FEIElementGeometryWrapper(thisElement));
734  double detJ = fabs( geoInterpolation->boundaryGiveTransformationJacobian( boundary, lcoords, FEIElementGeometryWrapper(thisElement) ) );
735 
736  Nbeta.resize(ndofids, ndof);
737  Nbeta.zero();
738  for (int i=0; i<tcount; i++) {
739  double val = computeBaseFunctionValue(i, gcoords);
740  for (int j=0; j<ndofids; j++) {
741  Nbeta.at(j+1, i*ndofids+j+1) = val;
742  }
743  }
744 
745  Nv.resize(ndofids, N.giveSize()*ndofids);
746  Nv.zero();
747  for (int i=0; i<ndofids; i++) {
748  for (int j=0; j<N.giveSize(); j++) {
749  Nv.at(i+1, ndofids*j+i+1) = N(j);
750  }
751  }
752 
753  FloatMatrix defNv, F, Finv;
754  double J=1.0;
755 
756  if (nlgeo) {
757  FloatArray elocal;
758  geoInterpolation->global2local(elocal, gcoords, FEIElementGeometryWrapper(thisElement));
759  computeDeformationGradient(F, thisElement, &elocal, tStep);
760 // J = F.giveDeterminant();
761  Finv.beInverseOf(F);
762  defNv.beProductOf(Finv, Nv);
763  } else {
764  J=1.0;
765  defNv = Nv;
766  }
767 
768  C.beTProductOf(Nbeta, defNv);
769  D.beTranspositionOf(C);
770 
771  gammaProd.plusProduct(D, a, J*detJ*gp->giveWeight()*normalSign);
772  vProd.plusProduct(C, gamma, J*detJ*gp->giveWeight()*normalSign);
773 
774  // Old:
775 /* FloatArray BaseFunctionValues;
776  BaseFunctionValues.resize(ndof);
777  BaseFunctionValues.zero();
778  for (int i=0; i<ndof; i++) {
779  BaseFunctionValues.at(i+1) = computeBaseFunctionValue(i, gcoords);
780  }
781 
782  C.beDyadicProductOf(N, BaseFunctionValues);
783  D.beTranspositionOf(C);
784 
785  myProd.plusProduct(C, a, detJ*gp->giveWeight()*normalSign);
786  myProdGamma.plusProduct(D, gamma, detJ*gp->giveWeight()*normalSign); */
787 
788  }
789 
790  if ( eNorms ) {
791  eNorms->assembleSquared( vProd, gamma_ids );
792  eNorms->assembleSquared( gammaProd, masterDofIDs);
793  }
794 
795  answer.assemble(gammaProd, gammaLoc);
796  answer.assemble(vProd, sideLocation);
797 // answer.assemble(myProd, gammaLoc);
798 // answer.assemble(myProdGamma, sideLocation);
799  }
800  }
801 }
802 
803 void
805  CharType type, ValueModeType mode,
806  const UnknownNumberingScheme &s)
807 {
808 
809  updateSminmax();
810 
811  IntArray gammaLoc;
812  gammaDman->giveLocationArray(gamma_ids, gammaLoc, s);
813 
814  FloatArray temp;
815  temp.resize(ndof);
816  temp.zero();
817 
818  int normalSign;
819 
820  for ( int thisSide = 0; thisSide <= 1; thisSide++ ) {
821  normalSign = sideSign [ thisSide ];
822  for ( size_t ielement = 0; ielement < element [ thisSide ].size(); ielement++ ) { // Loop over each element on this edge
823 
824  Element *thisElement = this->domain->giveElement( element [ thisSide ].at(ielement) );
825 
826  FEInterpolation *geoInterpolation = thisElement->giveInterpolation();
827 
828  std :: unique_ptr< IntegrationRule >iRule(geoInterpolation->giveBoundaryIntegrationRule(orderOfPolygon, side [ thisSide ].at(ielement) ));
829 
830  for ( auto gp: *iRule ) {
831 
832  FloatArray gcoords;
833  FloatArray lcoords = gp->giveNaturalCoordinates();
834 
835  // Find the value of parameter s which is the vert/horiz distance to 0
836  geoInterpolation->boundaryLocal2Global( gcoords, side [ thisSide ].at(ielement), lcoords, FEIElementGeometryWrapper( thisElement ) );
837  // Compute Jacobian
838  double detJ = fabs( geoInterpolation->boundaryGiveTransformationJacobian( side [ thisSide ].at(ielement), lcoords, FEIElementGeometryWrapper(thisElement) ) );
839 
840  for ( int j = 0; j < ndof; j++ ) {
841  FloatArray coord;
842 
843  double fVal = computeBaseFunctionValue(j, gcoords);
844 
845  temp.at(j+1) += normalSign*this->g.dotProduct(gcoords)*fVal*gp->giveWeight()*detJ;
846  }
847  }
848  }
849  }
850 
851  answer.assemble(temp, gammaLoc);
852 
853  // Finally, compute value of loadtimefunction
854  double factor = this->giveTimeFunction()->evaluate(tStep, mode);
855  answer.times(factor);
856 }
857 
859 {
860  return 1;
861 }
862 
864 {
865  if ( i == 1 ) {
866  return gammaDman.get();
867  } else {
868  return NULL;
869  }
870 }
871 
873 {
874  int x = 1;
875  for ( int i = 1; i <= n; i++ ) {
876  x = x * i;
877  }
878  return x;
879 }
880 
882 {
883  double f = 1.0;
884  for ( int i = 1; i <= k; i++ ) {
885  f = f * ( n - ( k - i ) ) / i;
886  }
887  return f;
888 }
889 
890 void WeakPeriodicBoundaryCondition :: getExponents(int term, int &i, int &j)
891 {
892  bool doContinue = true;
893 
894  // c is the number of the current term
895  int c = 0;
896 
897  // n is the order of the current polynomial (row in Pascals triangle)
898  int n = 0;
899 
900  while ( doContinue ) {
901  for ( int t = 0; t <= n; t++ ) {
902  c++;
903  if ( c == term ) {
904  i = n - t;
905  j = t;
906  doContinue = false;
907  break;
908  }
909  }
910  n++;
911  }
912 }
913 }
#define _IFT_WeakPeriodicBoundaryCondition_descritizationType
int giveNumberOfColumns() const
Returns number of columns of receiver.
Definition: floatmatrix.h:158
void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorm=NULL)
virtual DofManager * giveInternalDofManager(int i)
Gives an internal dof manager from receiver.
REGISTER_BoundaryCondition(BoundaryCondition)
Class and object Domain.
Definition: domain.h:115
virtual int assemble(const IntArray &loc, const FloatMatrix &mat)=0
Assembles sparse matrix from contribution of local elements.
void computeVectorOf(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Returns local vector of unknowns.
Definition: element.C:86
#define _IFT_WeakPeriodicBoundaryCondition_dofids
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition: femcmpnn.h:82
int giveNumberOfDofManagers() const
Returns number of dof managers in domain.
Definition: domain.h:432
Base class for all matrices stored in sparse format.
Definition: sparsemtrx.h:60
IRResultType initializeFrom(InputRecord *ir)
Initializes receiver according to object description stored in input record.
Definition: activebc.h:75
#define _IFT_WeakPeriodicBoundaryCondition_ngp
const IntArray & giveBoundaryList()
Returns list of element boundaries within set.
Definition: set.C:140
virtual double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo)=0
Evaluates the normal on the requested boundary.
void giveEdgeNormal(FloatArray &answer, int element, int side)
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
signed int sideSign[2]
sideSign is the sign of the normal for each side
ValueModeType
Type representing the mode of UnknownType or CharType, or similar types.
Definition: valuemodetype.h:78
WeakPeriodicBoundaryCondition(int n, Domain *d)
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes receiver according to object description stored in input record.
int tcount
Number of terms in polynomial.
#define _IFT_WeakPeriodicBoundaryCondition_elementSidesNegative
std::vector< int > side[2]
side[] keeps track of which side of the triangle is located along the boundary.
Abstract base class for all finite elements.
Definition: element.h:145
Base class for dof managers.
Definition: dofmanager.h:113
double evaluate(TimeStep *tStep, ValueModeType mode)
Returns the value of load time function at given time.
Definition: function.C:55
int giveNumberOfSpatialDimensions()
Returns number of spatial dimensions.
Definition: domain.C:1067
std::unique_ptr< Node > gammaDman
int posSet
Set containing positive side.
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
virtual FEInterpolation * giveInterpolation() const
Definition: element.h:629
IntArray dofids
ID of dofs on which weak periodicity is imposed.
#define min
#define _IFT_WeakPeriodicBoundaryCondition_order
int ndof
Number of degrees of freedom (number of terms)
int direction
Direction of normal.
#define _IFT_WeakPeriodicBoundaryCondition_nlgeo
void beMatrixForm(const FloatArray &aArray)
Definition: floatmatrix.C:1657
Class representing a general abstraction for finite element interpolation class.
Definition: feinterpol.h:132
Class representing "master" degree of freedom.
Definition: masterdof.h:92
virtual void assemble(SparseMtrx &answer, TimeStep *tStep, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale=1.0)
Assembles B.C.
void computeDeformationGradient(FloatMatrix &answer, Element *e, FloatArray *lcoord, TimeStep *tStep)
#define max
#define _IFT_WeakPeriodicBoundaryCondition_elementSidesPositive
FloatMatrix gsMatrix
gsMatrix contains coefficients for the Gram-Schmidt polynomials
IntArray surfaceIndexes
Keeps info on which coordinates varies over the surface.
int giveNumber()
Returns receiver&#39;s number.
Definition: timestep.h:129
void computeOrthogonalBasis()
Compute orthogonal polynomial basis using Gram-Smidth process.
Element * giveElement(int n)
Service for accessing particular domain fe element.
Definition: domain.C:160
#define M_PI
Definition: mathfem.h:52
double dotProduct(const FloatArray &x) const
Computes the dot product (or inner product) of receiver and argument.
Definition: floatarray.C:463
#define OOFEM_ERROR(...)
Definition: error.h:61
void clear()
Clears the array (zero size).
Definition: intarray.h:177
DofIDItem
Type representing particular dof type.
Definition: dofiditem.h:86
#define _IFT_WeakPeriodicBoundaryCondition_elementSidesPositiveSet
virtual void boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo)=0
Maps the local boundary coordinates to global.
void times(double f)
Multiplies receiver by factor f.
Definition: floatmatrix.C:1594
Abstract base class allowing to control the way, how equations are assigned to individual DOFs...
void getExponents(int n, int &i, int &j)
Compute exponent for term n.
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
virtual int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo)=0
Evaluates local coordinates from given global ones.
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Receiver becomes the result of the product of aMatrix and anArray.
Definition: floatarray.C:676
virtual double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo)=0
Evaluates the determinant of the transformation Jacobian on the requested boundary.
#define N(p, q)
Definition: mdm.C:367
Abstract base class for all active boundary conditions.
Definition: activebc.h:63
double at(int i, int j) const
Coefficient access function.
Definition: floatmatrix.h:176
void resize(int n)
Checks size of receiver towards requested bounds.
Definition: intarray.C:124
double computeProjectionCoefficient(int vIndex, int uIndex)
virtual void scale(double s)
Scales the receiver according to given value.
#define _IFT_WeakPeriodicBoundaryCondition_gradient
bool nlgeo
Use finite strains?
double binomial(double n, int k)
virtual void boundaryGiveNodes(IntArray &answer, int boundary)=0
Gives the boundary nodes for requested boundary number.
int giveNextFreeDofID(int increment=1)
Gives the next free dof ID.
Definition: domain.C:1411
int ngp
Number of Gausspoints used when integrating along the element edges.
Class representing vector of real numbers.
Definition: floatarray.h:82
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
void computeElementTangent(FloatMatrix &answer, Element *e, int boundary, TimeStep *tStep)
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
CharType
Definition: chartype.h:87
void resize(int rows, int cols)
Checks size of receiver towards requested bounds.
Definition: floatmatrix.C:1358
virtual void assembleVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorm=NULL)
Assembles B.C.
Class representing the general Input Record.
Definition: inputrecord.h:101
virtual void printYourself() const
Print receiver on stdout.
Definition: floatarray.C:747
virtual IntegrationRule * giveBoundaryIntegrationRule(int order, int boundary)
Sets up a suitable integration rule for integrating over the requested boundary.
Definition: feinterpol.C:63
void add(const FloatMatrix &a)
Adds matrix to the receiver.
Definition: floatmatrix.C:1023
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
void beTProductOf(const FloatMatrix &a, const FloatMatrix &b)
Assigns to the receiver product of .
Definition: floatmatrix.C:367
void assembleSquared(const FloatArray &fe, const IntArray &loc)
Assembles the array fe with each component squared.
Definition: floatarray.C:572
virtual void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIds=NULL)
Returns the location array for the boundary of the element.
Definition: element.C:446
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
double computeBaseFunctionValue(int baseID, FloatArray coordinate)
void printYourself() const
Prints matrix to stdout. Useful for debugging.
Definition: floatmatrix.C:1458
#define new
virtual int giveNumberOfInternalDofManagers()
Gives the number of internal dof managers.
void zero()
Zeroes all coefficient of receiver.
Definition: floatmatrix.C:1326
Domain * giveDomain() const
Definition: femcmpnn.h:100
#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
int giveSize() const
Definition: intarray.h:203
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
virtual double giveCoordinate(int i)
Definition: dofmanager.h:380
FloatArray g
Contains prescribed gradient.
int negSet
Set containing negative side.
int giveLabel() const
Definition: element.h:1055
the oofem namespace is to define a context or scope in which all oofem names are defined.
virtual void addElementSide(int elem, int side)
Adds element for active boundary condition.
Class implementing node in finite element mesh.
Definition: node.h:87
int giveNumber() const
Definition: femcmpnn.h:107
DofManager * giveDofManager(int n)
Service for accessing particular domain dof manager.
Definition: domain.C:314
void beInverseOf(const FloatMatrix &src)
Modifies receiver to become inverse of given parameter.
Definition: floatmatrix.C:835
#define _IFT_WeakPeriodicBoundaryCondition_elementSidesNegativeSet
double computeBaseFunctionValue2D(int baseID, FloatArray coordinate)
double computeBaseFunctionValue1D(int baseID, double coordinate)
int giveNumberOfRows() const
Returns number of rows of receiver.
Definition: floatmatrix.h:156
void computeBoundaryVectorOf(const IntArray &bNodes, const IntArray &dofIDMask, ValueModeType u, TimeStep *tStep, FloatArray &answer, bool padding=false)
Boundary version of computeVectorOf.
Definition: element.C:139
virtual void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo)=0
Evaluates the basis functions on the requested boundary.
Class representing integration point in finite element program.
Definition: gausspoint.h:93
#define OOFEM_WARNING(...)
Definition: error.h:62
Class representing solution step.
Definition: timestep.h:80
virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo)=0
Evaluates the matrix of derivatives of interpolation functions (shape functions) at given point...
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631
void plusProduct(const FloatMatrix &b, const FloatArray &s, double dV)
Adds the product .
Definition: floatarray.C:226
void giveExternalForcesVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, const UnknownNumberingScheme &s)

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