OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
qclinearstatic.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 "../sm/EngineeringModels/qclinearstatic.h"
36 #include "../sm/Quasicontinuum/fullsolveddomain.h"
37 #include "../sm/Elements/structuralelement.h"
38 #include "../sm/Elements/structuralelementevaluator.h"
39 #include "nummet.h"
40 #include "timestep.h"
41 #include "element.h"
42 #include "sparsemtrx.h"
43 #include "verbose.h"
44 #include "classfactory.h"
45 #include "datastream.h"
46 #include "contextioerr.h"
47 #include "classfactory.h"
48 
49 #include "qcnode.h"
50 #include "domain.h"
51 #include "dof.h"
52 #include "crosssection.h"
53 
54 #include "../sm/Quasicontinuum/quasicontinuum.h"
55 #include "../sm/Quasicontinuum/fullsolveddomain.h"
56 #include "../sm/Quasicontinuum/geometrygenerator.h"
57 #include "unknownnumberingscheme.h"
58 
59 #include "../sm/Quasicontinuum/quasicontinuumnumberingscheme.h"
60 
61  #include "t3dinterface.h"
62 #ifdef __T3D
63  #include "t3d.h"
64 #endif
65 
66 #ifdef __PARALLEL_MODE
67  #include "problemcomm.h"
68  #include "communicator.h"
69 #endif
70 
71 #include <typeinfo>
72 
73 namespace oofem {
74 REGISTER_EngngModel(QClinearStatic);
75 
76 QClinearStatic :: QClinearStatic(int i, EngngModel *_master) : LinearStatic(i, _master), loadVector(), displacementVector()
77 {
79 }
80 
81 
83 {
84  delete qcEquationNumbering;
85 }
86 
87 
88 
91 {
92  IRResultType result; // Required by IR_GIVE_FIELD macro
93 
95 
97 
98  if ( qcApproach == 0 || qcApproach == 1 || qcApproach == 2 || qcApproach == 3 ) {
99  // approach A0 = full solved particle model
100  // A1 hanging nodes, interpolation only
101  // A2 global homogenization
102  // A3 individual homogenization
103  } else {
104  OOFEM_ERROR("Invalid input field \"qcApproach\". Value: %d is not supported", qcApproach);
105  }
106 
107  if ( qcApproach > 0 ) { // apply qc
108  // Initialize Full-Solved Domain
109  this->initializeFullSolvedDomain(ir);
111 
113  if ( qcApproach > 1 ) {
114  homogenizationMtrxType = 1; // isotropic is default
116  }
117 
118 
120 
121  // Generate particles
122  generateParticles = 0;
124  if ( generateParticles == 0 ) { // 0 - defined in input file
125  } else if ( generateParticles == 1 ) { // 1 - generate + save
127  gg.generateParticles();
128  } else if ( generateParticles == 2 ) { // 2 - load
129  gg.loadParticles();
130  } else {
131  OOFEM_ERROR("Invalid input field \"genParticles\". Value: %d is not supported", generateParticles);
132  }
133 
134  // Generate links
135  generateLinks = 0;
137  if ( generateLinks == 0 ) {} else if ( generateLinks == 1 ) { // generate + save
139  gg.generateLinks();
140  } else if ( generateLinks == 2 ) { // load
141  gg.loadLinks();
142  } else {
143  OOFEM_ERROR("Invalid input field \"genLinks\". Value: %d is not supported", generateLinks);
144  }
145 
146  // Generate interpolation elements
149 
151  if ( generateInterpolationElements == 0 ) {
153  } else if ( generateInterpolationElements == 1 ) {
156  } else if ( generateInterpolationElements == 2 ) {
158  } else {
159  OOFEM_ERROR("Invalid input field \"GenInterpElem\". Value: %d is not supported", generateInterpolationElements);
160  }
161 
162 
163 
164  // test of combination of input geometry generating
165 #if DEBUG
166  if ( generateParticles == 1 && generateLinks != 1 ) {
167  OOFEM_ERROR("Links cannot be set manualy if particles are generated automaticaly");
168  }
170  OOFEM_ERROR("Interpolation elements cannot be set manually if particles are generated automaticaly");
171  }
172 #endif
173  } else { // if qcApproach == 0
174  generateParticles = 0;
175  generateLinks = 0;
177  }
178 
179 
180 
181 #ifdef __PARALLEL_MODE
182  if ( isParallel() ) {
184  communicator = new NodeCommunicator( this, commBuff, this->giveRank(),
185  this->giveNumberOfProcesses() );
186  }
187 
188 #endif
189 
190 
191  return IRRT_OK;
192 }
193 
194 
195 void
197 {
198  // checkout print of dof type before interpolation mesh is generated (1/2 = RN/HN)
199  /*
200  * for (int i=1; i<=this->giveDomain(1)->giveNumberOfDofManagers(); i++)
201  * {
202  * qcNode *n = dynamic_cast< qcNode * >( this->giveDomain(1)->giveDofManager(i) );
203  * OOFEM_LOG_INFO(" xxx: node %d type %d \n",n->giveGlobalNumber(),n->giveQcNodeType());
204  * }
205  */
206 
207  Quasicontinuum qc;
208  qc.setNoDimensions( this->giveDomain(1) );
209 
210  // interpolation mesh
212  if ( qcApproach > 0 ) {
218  }
219 
220  // checkout print of dof type after interpolation mesh is generated (1/2 = RN/HN)
221  /*
222  * OOFEM_LOG_INFO(" xxx: --------------------- \n");
223  * for ( int i = 1; i <= this->giveDomain(1)->giveNumberOfDofManagers(); i++ ) {
224  * //qcNode *n = dynamic_cast< qcNode * >( this->giveDomain(1)->giveDofManager(i) );
225  * Node *n = this->giveDomain(1)->giveNode(i);
226  * OOFEM_LOG_INFO( " xxx: node %d type %d \n", n->giveGlobalNumber(), n->giveQcNodeType() );
227  * }
228  */
229 
231 
232 
233  // apply QC
234 
235  if ( qcApproach == 0 ) { //A0 - fully solved model
236  // all nodes nad elements are activated
237  this->activatedNodeList.resize(this->giveDomain(1)->giveNumberOfDofManagers(), true);
238  this->activatedElementList.resize(this->giveDomain(1)->giveNumberOfElements(), true);
239  } else if ( qcApproach == 1 ) { // A1 - hanging nodes
240  // all nodes nad elements are activated
241  this->activatedNodeList.resize(this->giveDomain(1)->giveNumberOfDofManagers(), true);
242  this->activatedElementList.resize(this->giveDomain(1)->giveNumberOfElements(), true);
243 
244  qc.applyApproach1( this->giveDomain(1) );
245 
246  // postinitialize interpolation elements // ??km?? TO DO: giveInterpolationElem...
247  // TO DO: in EngngModel::postInitialize() elements are postinitialized again
248  for ( auto &el : this->giveDomain(1)->giveElements() ) {
249  el->postInitialize();
250  }
251  } else if ( qcApproach == 2 ) { // A2 - global homogenization
252  // elements need to be postintialized before computation of volume.
253  // TO DO: in EngngModel::postInitialize() elements are postinitialized again
254  // postinitialize interpolation elements // ??km?? TO DO: giveInterpolationElem...
255  for ( auto &el : this->giveDomain(1)->giveElements() ) {
256  el->postInitialize();
257  }
258 
259  double volumeOfInterpolationMesh = this->computeTotalVolumeOfInterpolationMesh( this->giveDomain(1) );
260  qc.applyApproach2(this->giveDomain(1), homogenizationMtrxType, volumeOfInterpolationMesh);
261  } else if ( qcApproach == 3 ) { // A3 - local homogenization
262  // elements need to be postintialized before computation of volume.
263  // TO DO: in EngngModel::postInitialize() elements are postinitialized again
264  // postinitialize interpolation elements // ??km?? TO DO: giveInterpolationElem...
265  for ( auto &el : this->giveDomain(1)->giveElements() ) {
266  el->postInitialize();
267  }
269  } else {
270  OOFEM_ERROR("unsupported qcApproach number");
271  }
272 
273 
274  // checkout print of activated elements
275  /*
276  * OOFEM_LOG_INFO(" xxx: --------------------- \n");
277  * for ( int i = 1; i <= ( int ) this->activatedElementList.size(); i++ ) {
278  * if ( this->activatedElementList.at(i - 1) ) {
279  * OOFEM_LOG_INFO(" active el %d d \n", i);
280  * }
281  * }
282  */
283 }
284 
285 
286 
288 {
290 }
291 
293 {
294  // initialize node eq numbering (for actived nodes only)
297  }
299 }
300 
301 
304 {
305  IRResultType result; // Required by IR_GIVE_FIELD macro
306 
311  // check input format
312 #ifdef DEBUG
313  if ( FullSolvedDomainRadius.giveSize() != 0 && FullSolvedDomainRadius.giveSize() % 4 != 0 ) {
314  OOFEM_ERROR("invalid format of FullSolvedDomainRadius");
315  }
316  if ( FullSolvedDomainBox.giveSize() != 0 && FullSolvedDomainBox.giveSize() % 6 != 0 ) {
317  OOFEM_ERROR("invalid format of FullSolvedDomainBox");
318  }
319 #endif
320 
321  return IRRT_OK;
322 }
323 
324 bool
326 {
327  FloatArray *coordinates = n->giveCoordinates();
328  // is tested node in FullSolvedDomainNodes
329  if ( FullSolvedDomainNodes.giveSize() != 0 ) {
330  for ( int i = 1; i <= FullSolvedDomainNodes.giveSize(); i++ ) {
331  if ( n->giveNumber() == FullSolvedDomainNodes.at(i) ) {
332  return true;
333  }
334  }
335  }
336 
337  // is tested node in FullSolvedDomainElements
338  if ( FullSolvedDomainElements.giveSize() != 0 ) {
339  for ( int i = 1; i <= FullSolvedDomainElements.giveSize(); i++ ) {
340  OOFEM_ERROR("Definition of Full Solved Domain by list of interpolation element has not been implemented yet");
341  // ??km?? TO DO:
342  //if ( "node n is in element with number FullSolvedDomainElements.at(i)" ) {
343  // return true;
344  //}
345  }
346  }
347 
348  // is tested node in FullSolvedDomainRadius
349  if ( FullSolvedDomainRadius.giveSize() != 0 ) {
350  for ( int i = 0; i <= FullSolvedDomainRadius.giveSize() / 4 - 1; i++ ) {
351  FloatArray vector;
352  vector.resize(3);
353  vector.at(1) = coordinates->at(1) - FullSolvedDomainRadius.at(4 * i + 1);
354  vector.at(2) = coordinates->at(2) - FullSolvedDomainRadius.at(4 * i + 2);
355  vector.at(3) = coordinates->at(3) - FullSolvedDomainRadius.at(4 * i + 3);
356  if ( vector.computeNorm() <= FullSolvedDomainRadius.at(4 * i + 4) ) {
357  return true;
358  }
359  }
360  }
361 
362  // is tested node in FullSolvedDomainBox
363  if ( FullSolvedDomainBox.giveSize() != 0 ) {
364  for ( int i = 0; i <= FullSolvedDomainBox.giveSize() / 6 - 1; i++ ) {
365  FloatArray A(3), B(3);
366  // left bottom corner coords
367  A.at(1) = FullSolvedDomainBox.at(6 * i + 1);
368  A.at(2) = FullSolvedDomainBox.at(6 * i + 2);
369  A.at(3) = FullSolvedDomainBox.at(6 * i + 3);
370  // right top corner coords
371  B.at(1) = FullSolvedDomainBox.at(6 * i + 4);
372  B.at(2) = FullSolvedDomainBox.at(6 * i + 5);
373  B.at(3) = FullSolvedDomainBox.at(6 * i + 4);
374 
375  if ( ( A.at(1) <= coordinates->at(1) ) && ( coordinates->at(1) <= B.at(1) ) && \
376  ( A.at(2) <= coordinates->at(2) ) && ( coordinates->at(2) <= B.at(2) ) && \
377  ( A.at(3) <= coordinates->at(3) ) && ( coordinates->at(3) <= B.at(3) ) ) {
378  return true;
379  }
380  }
381  }
382 
383 
384  return false;
385 }
386 
387 
388 void
390 {
391  int nol = 0; // number of links
392  int noe = d->giveNumberOfElements(); // number of all elements
393  for ( int i = 1; i <= noe; i++ ) { // over elements
394  int noen = d->giveElement(i)->giveNumberOfDofManagers(); // number of element nodes
395  if ( noen > 2 ) { // skip links with 2 nodes only
396  for ( int j = 1; j <= noen; j++ ) { // over element nodes
397  qcNode *n = dynamic_cast< qcNode * >( d->giveElement(i)->giveDofManager(j) );
398  if ( n ) {
399  n->setAsRepnode();
400  } else {
401  OOFEM_WARNING( "Node %d of interpolation element %d is not \"qcNode\", quasicontinuum is not applied in this node", d->giveElement(i)->giveGlobalNumber(), d->giveElement(i)->giveInternalDofManager(j)->giveGlobalNumber() );
402  }
403  }
404  } else if ( noen == 2 ) {
405  nol++;
406  }
407  }
408  // here we assume that in input file, interpolation elements ale listed continuously in the end of element list (after links )
409  numberOfIntepolationElements = noe - nol;
410 }
411 
412 
413 void
415 {
416  for ( int i = 1; i <= d->giveNumberOfDofManagers(); i++ ) {
417  qcNode *n = dynamic_cast< qcNode * >( d->giveDofManager(i) );
418  if ( n ) {
419  if ( !this->nodeInFullSolvedDomainTest(n) ) {
420  n->setAsHanging();
421  }
422  } else {
423  //OOFEM_ERROR("Node %d: Only \"qcNode\" type is supported in quasicontinuum simulation", i);
424  OOFEM_WARNING("Node %d is not \"qcNode\", quasicontinuum is not applied in this node", i);
425  }
426  }
427 }
428 
429 void
431 {
432  for ( int i = 1; i <= d->giveNumberOfDofManagers(); i++ ) {
433  // for ( Dof *dof: *this ) {
434  //for ( qcNode *n: *this ) {
435  qcNode *n = dynamic_cast< qcNode * >( d->giveDofManager(i) );
436  if ( n ) {
437  if ( this->nodeInFullSolvedDomainTest(n) ) {
438  n->setAsRepnode();
439  } else {
440  n->setAsHanging();
441  }
442  } else {
443  //OOFEM_ERROR("Node %d: Only \"qcNode\" type is supported in quasicontinuum simulation", i);
444  OOFEM_WARNING("Node %d is not \"qcNode\", quasicontinuum is not applied in this node", i);
445  }
446  }
447 }
448 
449 
450 void
452 {
453  // interpolation mesh
454  if ( generateInterpolationElements == 0 ) {
455  // interpolation mesh is defined in input file - elements with material number qcMatNumber
456  } else if ( generateInterpolationElements == 1 ) {
458  } else if ( generateInterpolationElements == 2 ) {
459  this->interpolationMeshNodes = this->loadInterpolationMesh( this->giveDomain(1) );
460  }
461 }
462 
463 std :: vector< IntArray >
465 {
466  std :: vector< IntArray >newMeshNodes;
467 #ifdef __T3D
468  T3DInterface *t3dInterface = new T3DInterface( this->giveDomain(1) );
469 #endif
470  std :: vector< FloatArray >nodeCoords;
471  std :: vector< IntArray >meshNodes;
472  IntArray cellTypes;
473 
474  char options_string [ 128 ] = "";
475  const char *t3dInFile; //char *t3dInFile = "interpolationMesh_t3d.in";
476  const char *t3dOutFile; //char *t3dOutFile = "interpolationMesh_t3d.out";
477 
478  std :: string temp;
479  temp = t3dFileName;
480  temp.append(".oofem.t3d.out");
481  t3dOutFile = temp.c_str();
482  t3dInFile = t3dFileName.c_str();
483  sprintf(options_string, "-i %s -o %s -S -u %f -Q -W", t3dInFile, t3dOutFile, defaultT3DMeshSize);
484 
485 #ifdef __T3D
486  if ( generateInterpolationElements == 1 ) {
487  /* run T3D to generate mesh */
488  try {
489  t3d_main(NULL, options_string);
490  } catch(int exit_code) {
491  fprintf(stderr, "T3d was prematuraly terminated with error code %d\n\n", exit_code);
492  }
493  }
494 #else
495  OOFEM_ERROR("OOFEM is NOT compiled with T3D option but T3D in needed");
496 #endif
497 
499  // create interpolation mesh from t3d output file
500 #ifdef __T3D
501  t3dInterface->createQCInterpolationMesh(t3dOutFile, nodeCoords, meshNodes, cellTypes);
502 #endif
503 
504  // map mesh to position of particles
505  newMeshNodes = this->transformMeshToParticles(this->giveDomain(1), nodeCoords, meshNodes);
506 
507  // degenerated elements have been removed
508  // check if mesch is consistent after removal. ??km?? TO DO ?? How to check it?
509  }
510  return newMeshNodes;
511 }
512 
513 std :: vector< IntArray >
515 {
516  std :: vector< IntArray >newMeshNodes;
517  //#ifdef __T3D
518  T3DInterface *t3dInterface = new T3DInterface( this->giveDomain(1) );
519  //#endif
520  std :: vector< FloatArray >nodeCoords;
521  std :: vector< IntArray >meshNodes;
522  IntArray cellTypes;
523 
524  const char *t3dOutFile; //char *t3dOutFile = "interpolationMesh_t3d.out";
525 
526  t3dOutFile = t3dFileName.c_str();
527 
528  // create interpolation mesh from given t3d output file
529  //#ifdef __T3D
530  t3dInterface->createQCInterpolationMesh(t3dOutFile, nodeCoords, meshNodes, cellTypes);
531  //#endif
532 
533  // map mesh to position of particles
534  newMeshNodes = this->transformMeshToParticles(this->giveDomain(1), nodeCoords, meshNodes);
535 
536  // degenerated elements have been removed
537  // check if mesch is consistent after removal. ??km?? TO DO ?? How to check it?
538  return newMeshNodes;
539 }
540 
541 
542 std :: vector< IntArray >
543 QClinearStatic :: transformMeshToParticles(Domain *d, std :: vector< FloatArray > &nodeCoords, std :: vector< IntArray > &meshNodes)
544 // all nodes in meshNodes are shifted to the position of neares particle (i.e. node in domain)
545 // this node is set as repnode
546 // elements degenerated (by the shift of two vertexes into the same particle) are removed from the list
547 //
548 {
549  // number of particles (nodes in domain)
550  //int nop = this->giveDomain(1)->giveNumberOfDofManagers() ; // TO DO we assume that all DofManagers all nodes (particles)
551  // number of (mesh) nodes
552  int nomn = nodeCoords.size();
553  // number of (mesh) element
554  int nome = meshNodes.size();
555 
556  //newMeshNodes=meshNodes;
557  std :: vector< IntArray >newMeshNodes;
558  newMeshNodes.clear();
559  //particleOfMeshNode=zeros(1,nomn);
560  IntArray newNodeNumbers;
561  newNodeNumbers.resize(nomn);
562 
563  // loop over all nodes of mesh elments
564  for ( int i = 1; i <= nomn; i++ ) {
565  // ??km?? TO DO: use octree in "findNearestParticle", now it is not effective
566  // find nearest node and set him as repnode (is neares node QCnode?)
567  qcNode *nearestParticle = dynamic_cast< qcNode * >( findNearestParticle(d, nodeCoords [ i - 1 ]) );
568  if ( nearestParticle ) {
569  if ( nearestParticle->giveQcNodeType() != 1 ) { // if nearest node is not repnode
570  nearestParticle->setAsRepnode();
571  }
572  } else {
573  OOFEM_ERROR("Vertex of interpolation mesh is shifted to node which is not \"qcNode\"");
574  // ??km?? TO DO: add combination of qcNode and normal node in one input. Then not necessarily qcNode is needed.
575  // Test if node "nearestParticle" has independet DOFs should be enough.
576  // OOFEM_WARNING(" ");
577  }
578 
579  nodeCoords [ i - 1 ] = * nearestParticle->giveCoordinates();
580  newNodeNumbers [ i - 1 ] = nearestParticle->giveNumber();
581  }
582 
583  //
584  // check and remove degenerated elements
585  //
586 
587 
588  // for 2D triangles
589  if ( meshNodes [ 0 ].giveSize() == 3 ) {
590  // TO DO: how to do not consider interpolation elements in user define area
591  // ??km?? for example in FSD it is better without interpolation elements
592  // check if two or more vertexes were shifted to the same particle -- element degeneration
593  for ( int i = 1; i <= nome; i++ ) {
594  int n1 = meshNodes [ i - 1 ].at(1); // node numbers
595  int n2 = meshNodes [ i - 1 ].at(2);
596  int n3 = meshNodes [ i - 1 ].at(3);
597  if ( newNodeNumbers.at(n1) == newNodeNumbers.at(n2) || \
598  newNodeNumbers.at(n1) == newNodeNumbers.at(n3) || \
599  newNodeNumbers.at(n2) == newNodeNumbers.at(n3) ) {
600  continue; // skip degenerate element
601  } else { // check degeneration to negative volume
602  // ??km?? TO DO: how to check negative volume in 2D
603  // overlaping elements may cause problems in homogenization
604  double detJ = 1.0;
605  if ( detJ <= 0 ) {
606  OOFEM_WARNING("%d-th interpolation element degenerates to negative volume", i);
607  } else { // element is ok and will be saved
608  IntArray OkmeshNodes(3);
609  OkmeshNodes.at(1) = newNodeNumbers.at(n1);
610  OkmeshNodes.at(2) = newNodeNumbers.at(n2);
611  OkmeshNodes.at(3) = newNodeNumbers.at(n3);
612  newMeshNodes.push_back(OkmeshNodes);
613  }
614  }
615  } // over elements in 2D
616 
617  // for 3D tetras
618  } else {
619  for ( int i = 1; i <= nome; i++ ) {
620  // TO DO: how to do not consider interpolation elements in user define area
621  // ??km?? for example in FSD it is better without interpolation elements
622 
623  // check if two or more vertexes were shifted to the same particle -- element degeneration
624  int n1 = meshNodes [ i - 1 ].at(1); // node numbers
625  int n2 = meshNodes [ i - 1 ].at(2);
626  int n3 = meshNodes [ i - 1 ].at(3);
627  int n4 = meshNodes [ i - 1 ].at(4);
628  if ( newNodeNumbers.at(n1) == newNodeNumbers.at(n2) || \
629  newNodeNumbers.at(n1) == newNodeNumbers.at(n3) || \
630  newNodeNumbers.at(n1) == newNodeNumbers.at(n4) || \
631  newNodeNumbers.at(n2) == newNodeNumbers.at(n3) || \
632  newNodeNumbers.at(n2) == newNodeNumbers.at(n4) || \
633  newNodeNumbers.at(n3) == newNodeNumbers.at(n4) ) {
634  continue; // skip degenerate element
635  } else { // check degeneration to negative volume
636  double x1 = d->giveDofManager( newNodeNumbers.at(n1) )->giveCoordinates()->at(1);
637  double y1 = d->giveDofManager( newNodeNumbers.at(n1) )->giveCoordinates()->at(2);
638  double z1 = d->giveDofManager( newNodeNumbers.at(n1) )->giveCoordinates()->at(3);
639  double x2 = d->giveDofManager( newNodeNumbers.at(n2) )->giveCoordinates()->at(1);
640  double y2 = d->giveDofManager( newNodeNumbers.at(n2) )->giveCoordinates()->at(2);
641  double z2 = d->giveDofManager( newNodeNumbers.at(n2) )->giveCoordinates()->at(3);
642  double x3 = d->giveDofManager( newNodeNumbers.at(n3) )->giveCoordinates()->at(1);
643  double y3 = d->giveDofManager( newNodeNumbers.at(n3) )->giveCoordinates()->at(2);
644  double z3 = d->giveDofManager( newNodeNumbers.at(n3) )->giveCoordinates()->at(3);
645  double x4 = d->giveDofManager( newNodeNumbers.at(n4) )->giveCoordinates()->at(1);
646  double y4 = d->giveDofManager( newNodeNumbers.at(n4) )->giveCoordinates()->at(2);
647  double z4 = d->giveDofManager( newNodeNumbers.at(n4) )->giveCoordinates()->at(3);
648  double detJ = ( x4 - x1 ) * ( y2 - y1 ) * ( z3 - z1 ) - ( x4 - x1 ) * ( y3 - y1 ) * ( z2 - z1 ) + ( x3 - x1 ) * ( y4 - y1 ) * ( z2 - z1 ) - ( x2 - x1 ) * ( y4 - y1 ) * ( z3 - z1 ) + ( x2 - x1 ) * ( y3 - y1 ) * ( z4 - z1 ) - ( x3 - x1 ) * ( y2 - y1 ) * ( z4 - z1 );
649  if ( detJ <= 0 ) {
650  OOFEM_WARNING("%d-th interpolation element degenerates to negative volume", i);
651  continue;
652  } else { // element is ok and will be saved
653  IntArray OkmeshNodes(4);
654  OkmeshNodes.at(1) = newNodeNumbers.at(n1);
655  OkmeshNodes.at(2) = newNodeNumbers.at(n2);
656  OkmeshNodes.at(3) = newNodeNumbers.at(n3);
657  OkmeshNodes.at(4) = newNodeNumbers.at(n4);
658  newMeshNodes.push_back(OkmeshNodes);
659  }
660  }
661  } // over elements
662  } // in 3D
663 
664  return newMeshNodes;
665 }
666 
667 double
669 // TO DO: computeVolumeAreaOrLength() is not working
670 {
671  int dim = d->giveNumberOfSpatialDimensions();
672  // loop ovel all elements
673  double volume = 0.;
674  double totalVolume = 0.;
675 
676  if ( dim == 2 ) {
677  double th;
678 
679  for ( int i = 1; i <= d->giveNumberOfElements(); i++ ) {
680  // skip links with 2 nodes
681  // ??KM?? TO DO: use only list of interpolation elements
682  if ( d->giveElement(i)->giveNumberOfDofManagers() > 2 ) {
683  volume = d->giveElement(i)->computeVolumeAreaOrLength();
684  th = d->giveElement(i)->giveCrossSection()->give(CS_Thickness, NULL);
685  totalVolume += volume / th;
686  }
687  }
688  } else if ( dim == 3 ) {
689  for ( int i = 1; i <= d->giveNumberOfElements(); i++ ) {
690  // skip links with 2 nodes
691  // ??KM?? TO DO: use only list of interpolation elements
692  if ( d->giveElement(i)->giveNumberOfDofManagers() > 2 ) {
693  volume = d->giveElement(i)->computeVolumeAreaOrLength();
694  totalVolume += volume;
695  }
696  }
697  } else {
698  OOFEM_ERROR("Invalid number of dimensions. Only 2d and 3d domains are supported in QC simulation. \n");
699  }
700 
701  return totalVolume;
702 }
703 
704 
705 DofManager *
707 {
708  // TO DO: use octree here
709  double minDistance = 1.0e100;
710  double distance;
711  DofManager *p;
712  // loop over all particles (nodes in existing domain)
713  for ( int i = 1; i <= d->giveNumberOfDofManagers(); i++ ) {
714  distance = coords.distance( d->giveDofManager(i)->giveCoordinates() );
715  if ( distance < minDistance ) {
716  minDistance = distance;
717  p = d->giveDofManager(i);
718  }
719  }
720  if ( p ) {
721  return p;
722  } else {
723  OOFEM_ERROR( "Neares particle for point [%d, %d] not found", coords.at(1), coords.at(2) );
724  return NULL;
725  }
726 }
727 
730 {
732  p = & Fullsolveddomain;
733  return p;
734 }
735 
736 
737 void
739 {
740  this->activatedNodeList.clear();
741  this->activatedNodeList.resize(nodeList.giveSize(), false);
742  for ( int i = 1; i <= nodeList.giveSize(); i++ ) {
743  // if node is activated or master node
744  if ( ( nodeList.at(i) == 1 ) || ( d->giveNode(i)->giveQcNodeType() == 1 ) ) {
745  this->activatedNodeList [ i - 1 ] = true;
746  }
747  }
748 }
749 
750 void
752 {
753  this->activatedElementList.clear();
754  this->activatedElementList.resize(elemList.giveSize(), false);
755  for ( int i = 1; i <= elemList.giveSize(); i++ ) {
756  // if element is activated
757  if ( elemList.at(i) == 1 ) {
758  this->activatedElementList [ i - 1 ] = true;
759  }
760  }
761 }
762 } // end namespace oofem
CrossSection * giveCrossSection()
Definition: element.C:495
void applyApproach3(Domain *d, int homMtrxType)
virtual bool nodeInFullSolvedDomainTest(Node *n)
#define _IFT_QuasiContinuum_generate_Links
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes receiver according to object description in input reader.
Definition: linearstatic.C:94
QCFullsolveddomain Fullsolveddomain
#define _IFT_QuasiContinuum_t3d_File_Name
Class and object Domain.
Definition: domain.h:115
virtual int giveQcNodeType()
Definition: qcnode.h:98
virtual void setRepNodesInVerticesOfInterpolationMesh(Domain *d)
General simplification for Quasicontinuum simulation.
void applyApproach1(Domain *d)
Information about fullsolved domain in CQ simulation.
int giveGlobalNumber() const
Definition: dofmanager.h:501
virtual IRResultType initializeFrom(InputRecord *ir)
int giveNumberOfDofManagers() const
Returns number of dof managers in domain.
Definition: domain.h:432
virtual void solveYourself()
Starts solution process.
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
int giveGlobalNumber() const
Definition: element.h:1059
void setActivatedNodeList(IntArray nodeList, Domain *d)
#define _IFT_QuasiContinuum_mtrx_type
virtual void solveYourselfAt(TimeStep *tStep)
Solves problem for given time step.
Definition: linearstatic.C:189
FloatArray FullSolvedDomainBox
virtual FloatArray * giveCoordinates()
Definition: dofmanager.h:382
bool isParallel() const
Returns true if receiver in parallel mode.
Definition: engngm.h:1056
#define _IFT_QuasiContinuum_T3D_Interpolation_Mesh_size
Base class for dof managers.
Definition: dofmanager.h:113
int giveNumberOfProcesses() const
Returns the number of collaborating processes.
Definition: engngm.h:1060
void createInterpolationElements(Domain *d)
int giveNumberOfElements() const
Returns number of elements in domain.
Definition: domain.h:434
virtual void setAsRepnode()
Definition: qcnode.C:241
int giveNumberOfSpatialDimensions()
Returns number of spatial dimensions.
Definition: domain.C:1067
#define _IFT_QuasiContinuum_generate_Interpolation_Elements
REGISTER_EngngModel(ProblemSequence)
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
virtual int giveNumberOfDofManagers() const
Definition: element.h:656
void setupInterpolationMesh(Domain *d, int generateInterpolationElements, int interpolationElementsMaterialNumber, std::vector< IntArray > *newMeshNodes)
QClinearStatic(int i, EngngModel *_master=NULL)
virtual void createInterpolationMeshNodes(Domain *d)
virtual double computeVolumeAreaOrLength()
Computes the volume, area or length of the element depending on its spatial dimension.
Definition: element.C:1059
virtual void postInitialize()
Performs post-initialization for all the problem contents (which is called after initializeFrom).
double distance(const FloatArray &x) const
Computes the distance between position represented by receiver and position given as parameter...
Definition: floatarray.C:489
QuasicontinuumNumberingscheme * qcEquationNumbering
#define _IFT_FullSolvedDomain_radius
IRResultType initializeLinkGenerator(InputRecord *ir)
virtual DofManager * findNearestParticle(Domain *d, FloatArray coords)
virtual void setAsHanging()
Definition: qcnode.C:249
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes receiver according to object description in input reader.
#define _IFT_QuasiContinuum_approach
Element * giveElement(int n)
Service for accessing particular domain fe element.
Definition: domain.C:160
#define OOFEM_ERROR(...)
Definition: error.h:61
void setActivatedElementList(IntArray elemList)
#define _IFT_QuasiContinuum_interp_Mat_Number
virtual void init(Domain *domain, std::vector< bool > activatedNodeList, TimeStep *tStep)
Initializes the receiver.
Class implementing hanging node connected to other nodes (masters) using interpolation.
Definition: qcnode.h:64
ProblemCommunicator * communicator
Communicator.
Definition: engngm.h:303
virtual void solveYourself()
Starts solution process.
Definition: linearstatic.C:172
CommunicatorBuff * commBuff
Common Communicator buffer.
Definition: engngm.h:301
void setNoDimensions(Domain *d)
virtual void postInitialize()
Performs post-initialization for all the problem contents (which is called after initializeFrom).
Definition: engngm.C:1869
std::vector< bool > activatedElementList
virtual std::vector< IntArray > transformMeshToParticles(Domain *d, std::vector< FloatArray > &nodeCoords, std::vector< IntArray > &meshNodes)
void resize(int n)
Checks size of receiver towards requested bounds.
Definition: intarray.C:124
#define _IFT_FullSolvedDomain_elements
FloatArray FullSolvedDomainNodes
virtual DofManager * giveInternalDofManager(int i) const
Returns i-th internal element dof manager of the receiver.
Definition: element.h:238
void applyApproach2(Domain *d, int homMtrxType, double volumeOfInterpolationMesh)
Initializes the variable VERBOSE, in order to get a few intermediate messages on screen: beginning an...
virtual std::vector< IntArray > generateInterpolationMesh(Domain *d)
Class representing vector of real numbers.
Definition: floatarray.h:82
virtual void updateNodeTypes(Domain *d)
virtual void solveYourselfAt(TimeStep *tStep)
Solves problem for given time step.
IRResultType
Type defining the return values of InputRecord reading operations.
Definition: irresulttype.h:47
virtual double give(CrossSectionProperty a, GaussPoint *gp)
Returns the value of cross section property at given point.
Definition: crosssection.C:151
#define _IFT_FullSolvedDomain_nodes
virtual QCFullsolveddomain * giveFullSolvedDomain()
Returns Fullsolved domain to which receiver is associated.
double computeNorm() const
Computes the norm (or length) of the vector.
Definition: floatarray.C:840
void addCrosssectionToInterpolationElements(Domain *d)
Class representing the general Input Record.
Definition: inputrecord.h:101
std::vector< IntArray > interpolationMeshNodes
This class implements linear static engineering problem.
Definition: linearstatic.h:63
IRResultType initializeParticleGenerator(InputRecord *ir)
#define _IFT_QuasiContinuum_generate_Particles
virtual int giveQcNodeType()
Definition: node.h:183
int giveRank() const
Returns domain rank in a group of collaborating processes (0..groupSize-1)
Definition: engngm.h:1058
virtual double computeTotalVolumeOfInterpolationMesh(Domain *d)
virtual void setQCNodeType(Domain *d)
#define _IFT_FullSolvedDomain_box
Numbering scheme that takes into account only list of selected nodes.
FloatArray FullSolvedDomainElements
virtual FloatArray * giveCoordinates()
Definition: node.h:114
The Communicator and corresponding buffers (represented by this class) are separated in order to allo...
Definition: communicator.h:60
Abstract base class representing the "problem" under consideration.
Definition: engngm.h:181
FloatArray FullSolvedDomainRadius
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:78
int giveSize() const
Definition: intarray.h:203
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
Node * giveNode(int n)
Service for accessing particular domain node.
Definition: domain.h:371
the oofem namespace is to define a context or scope in which all oofem names are defined.
DofManager * giveDofManager(int i) const
Definition: element.C:514
Domain * giveDomain(int n)
Service for accessing particular problem domain.
Definition: engngm.C:1720
std::vector< bool > activatedNodeList
Class implementing node in finite element mesh.
Definition: node.h:87
virtual std::vector< IntArray > loadInterpolationMesh(Domain *d)
#define IR_GIVE_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:69
int giveNumber() const
Definition: femcmpnn.h:107
DofManager * giveDofManager(int n)
Service for accessing particular domain dof manager.
Definition: domain.C:314
virtual IRResultType initializeFullSolvedDomain(InputRecord *ir)
#define OOFEM_WARNING(...)
Definition: error.h:62
Class representing solution step.
Definition: timestep.h:80
This class represents the interface to t3d mesh generation package.
Definition: t3dinterface.h:55
int createQCInterpolationMesh(const char *t3dOutFile, std::vector< FloatArray > &nodeCoords, std::vector< IntArray > &cellNodes, IntArray &cellTypes)
Definition: t3dinterface.C:736
Generate random geometry of particles and links for CQ simulation.
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:30 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011