OOFEM 3.0
Loading...
Searching...
No Matches
primaryfield.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 - 2025 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 "primaryfield.h"
36#include "spatiallocalizer.h"
37#include "dofmanager.h"
38#include "dof.h"
39#include "element.h"
40#include "timestep.h"
41#include "datastream.h"
42#include "contextioerr.h"
43#include "engngm.h"
45#include "initialcondition.h"
46#include "boundarycondition.h"
47
48namespace oofem {
49PrimaryField :: PrimaryField(EngngModel *a, int idomain,
50 FieldType ft, int nHist) : Field(ft), solutionVectors(nHist + 1), prescribedVectors(nHist + 1), solStepList(nHist + 1, a)
51{
52 this->actualStepNumber = -999;
53 this->actualStepIndx = 0;
54 this->nHistVectors = nHist;
55
56 emodel = a;
57 domainIndx = idomain;
58}
59
60PrimaryField :: ~PrimaryField()
61{ }
62
63
64void
65PrimaryField :: storeDofManager(TimeStep *tStep, DofManager &dman)
66{
67 for ( Dof *dof: dman ) {
68 int eq = dof->giveEqn();
69 TimeStep *step = tStep;
70 for ( int hist = 0; hist < this->nHistVectors; ++hist ) {
71 if ( eq > 0 ) {
72 FloatArray *vec = this->giveSolutionVector( resolveIndx(tStep, 0) );
73 dof->updateUnknownsDictionary(step, VM_Total, vec->at(eq));
74 } else if ( eq < 0 ) {
75 FloatArray *vec = this->givePrescribedVector( resolveIndx(tStep, 0) );
76 dof->updateUnknownsDictionary(step, VM_Total, vec->at(-eq));
77 }
78 step = tStep->givePreviousStep();
79 }
80 }
81}
82
83void
84PrimaryField :: storeInDofDictionaries(TimeStep *tStep)
85{
86 Domain *d = emodel->giveDomain(domainIndx);
87 for ( auto &dman : d->giveDofManagers() ) {
88 this->storeDofManager(tStep, *dman);
89 }
90
91 for ( auto &elem : d->giveElements() ) {
92 int ndman = elem->giveNumberOfInternalDofManagers();
93 for ( int i = 1; i <= ndman; i++ ) {
94 this->storeDofManager(tStep, *elem->giveInternalDofManager(i));
95 }
96 }
97
98 for ( auto &bc : d->giveBcs() ) {
99 int ndman = bc->giveNumberOfInternalDofManagers();
100 for ( int i = 1; i <= ndman; i++ ) {
101 this->storeDofManager(tStep, *bc->giveInternalDofManager(i));
102 }
103 }
104}
105
106
107void
108PrimaryField :: readDofManager(TimeStep *tStep, DofManager &dman)
109{
110 for ( Dof *dof: dman ) {
111 int eq = dof->giveEqn();
112 TimeStep *step = tStep;
113 for ( int hist = 0; hist < this->nHistVectors; ++hist ) {
114 if ( eq > 0 ) {
115 FloatArray *vec = this->giveSolutionVector( resolveIndx(tStep, 0));
116 vec->at(eq) = dof->giveUnknownsDictionaryValue(step, VM_Total);
117 } else if ( eq < 0 ) {
118 FloatArray *vec = this->givePrescribedVector( resolveIndx(tStep, 0) );
119 vec->at(-eq) = dof->giveUnknownsDictionaryValue(step, VM_Total);
120 }
121 step = tStep->givePreviousStep();
122 }
123 }
124}
125
126
127void
128PrimaryField :: readFromDofDictionaries(TimeStep *tStep)
129{
130 Domain *d = emodel->giveDomain(domainIndx);
131 //int neq = this->emodel->giveNumberOfDomainEquations(domainIndx, EModelDefaultEquationNumbering());
132 //int peq = this->emodel->giveNumberOfDomainEquations(domainIndx, EModelDefaultPrescribedEquationNumbering());
133 for ( auto &dman : d->giveDofManagers() ) {
134 this->readDofManager(tStep, *dman);
135 }
136
137 for ( auto &elem : d->giveElements() ) {
138 int ndman = elem->giveNumberOfInternalDofManagers();
139 for ( int i = 1; i <= ndman; i++ ) {
140 this->readDofManager(tStep, *elem->giveInternalDofManager(i));
141 }
142 }
143
144 for ( auto &bc : d->giveBcs() ) {
145 int ndman = bc->giveNumberOfInternalDofManagers();
146 for ( int i = 1; i <= ndman; i++ ) {
147 this->readDofManager(tStep, *bc->giveInternalDofManager(i));
148 }
149 }
150}
151
152
153void
154PrimaryField :: initialize(ValueModeType mode, TimeStep *tStep, FloatArray &answer, const UnknownNumberingScheme &s)
155{
156 if ( mode == VM_Total ) {
157 answer = * ( this->giveSolutionVector(tStep) );
158 } else if ( mode == VM_Incremental ) {
159 int indxm1 = this->resolveIndx(tStep, -1);
160 answer = * ( this->giveSolutionVector(tStep) );
161 answer.subtract( * this->giveSolutionVector(indxm1) );
162 } else {
163 OOFEM_ERROR("unsupported mode %s", __ValueModeTypeToString(mode));
164 }
165}
166
167void
168PrimaryField :: applyDefaultInitialCondition()
169{
170 int neq = emodel->giveNumberOfDomainEquations( domainIndx, EModelDefaultEquationNumbering() );
171 int npeq = emodel->giveNumberOfDomainEquations( domainIndx, EModelDefaultPrescribedEquationNumbering() );
172 for ( auto &s : solutionVectors ) {
173 s.resize(neq);
174 s.zero();
175 }
176 for ( auto &s : prescribedVectors ) {
177 s.resize(npeq);
178 s.zero();
179 }
180
181 TimeStep *tStep = emodel->giveSolutionStepWhenIcApply();
182 Domain *d = emodel->giveDomain(domainIndx);
183 int indxm0;
184 if ( tStep == NULL ) {
185 indxm0 = 1;
186 } else {
187 indxm0 = this->resolveIndx(tStep, 0);
188 }
189 FloatArray *f0 = this->giveSolutionVector(indxm0);
190 FloatArray *p0 = this->givePrescribedVector(indxm0);
191 for ( auto &dman : d->giveDofManagers() ) {
192 for ( auto &dof : *dman ) {
193 int icid = dof->giveIcId();
194 if ( icid > 0 && dof->isPrimaryDof() ) {
195 InitialCondition *ic = d->giveIc(icid);
196 if ( ic->hasConditionOn(VM_Total) ) {
197 FloatArray c = dman->giveCoordinates();
198 double val = ic->give(VM_Total, c);
199 int eq = dof->giveEqn();
200 dof->updateUnknownsDictionary(tStep, VM_Total, val);
201 if ( eq > 0 ) {
202 f0->at(eq) = val;
203 } else if ( eq < 0 ) {
204 p0->at(-eq) = val;
205 }
206 }
207 }
208 }
209 }
210 // Apply ICs that use sets.
211 for ( auto &ic : emodel->giveDomain(domainIndx)->giveIcs() ) {
212 this->applyInitialCondition(*ic);
213 }
214}
215
216
217void
218PrimaryField :: applyInitialCondition(InitialCondition &ic)
219{
220 if ( ic.giveSetNumber() == 0 ) {
221 return;
222 }
223
224 Domain *d = ic.giveDomain();
225 Set *set = d->giveSet(ic.giveSetNumber());
226 TimeStep *tStep = emodel->giveSolutionStepWhenIcApply();
227 int indxm0 = this->resolveIndx(tStep, 0);
228 int indxm1 = this->resolveIndx(tStep, -1);
229 FloatArray *f0 = this->giveSolutionVector(indxm0);
230 FloatArray *f1 = this->giveSolutionVector(indxm1);
231 FloatArray *p0 = this->givePrescribedVector(indxm0);
232 FloatArray *p1 = this->givePrescribedVector(indxm1);
233
234 // We have to set initial value, and velocity, for this particular primary field.
235 for ( int inode : set->giveNodeList() ) {
236 DofManager *dman = d->giveDofManager(inode);
237 FloatArray c = dman->giveCoordinates();
238 double tot0 = 0., tot1 = 0.;
239 if ( ic.hasConditionOn(VM_Total) ) {
240 tot0 = ic.give(VM_Total, c);
241 }
242 if ( ic.hasConditionOn(VM_Incremental) ) {
243 tot1 = tot0 - ic.give(VM_Incremental, c);
244 } else if ( ic.hasConditionOn(VM_Velocity) ) {
245
246 tot1 = tot0 - ic.give(VM_Velocity,c) * tStep->giveTimeIncrement();
247 } else {
248 tot1 = tot0;
249 }
250 for ( auto &dof : *dman ) {
251 int eq = dof->giveEqn();
252 if ( eq > 0 ) {
253 f0->at(eq) = tot0;
254 f1->at(eq) = tot1;
255 } else if ( eq < 0 ) {
256 p0->at(-eq) = tot0;
257 p1->at(-eq) = tot1;
258 }
259 }
260 }
261}
262
263
264void
265PrimaryField :: applyBoundaryCondition(TimeStep *tStep)
266{
267 Domain *d = emodel->giveDomain(domainIndx);
268 FloatArray *f = this->givePrescribedVector(resolveIndx(tStep, 0));
269 for ( auto &dman : d->giveDofManagers() ) {
270 for ( auto &dof : *dman ) {
271 int peq = - dof->giveEqn();
272 if ( peq > 0 ) {
273 int bcid = dof->giveBcId();
274 f->at(peq) = static_cast< BoundaryCondition* >(d->giveBc(bcid))->give(dof, VM_Total, tStep->giveTargetTime());
275 }
276 }
277 }
278
279 for ( auto &bc : d->giveBcs() ) {
280 BoundaryCondition *dbc = dynamic_cast< BoundaryCondition* >(bc.get());
281 if ( dbc ) {
282 this->applyBoundaryCondition(*dbc, tStep);
283 }
284 }
285}
286
287
288void
289PrimaryField :: applyBoundaryCondition(BoundaryCondition &bc, TimeStep *tStep)
290{
291 if ( bc.giveSetNumber() == 0 ) {
292 return;
293 }
294
295 Domain *d = bc.giveDomain();
296 Set *set = d->giveSet(bc.giveSetNumber());
297 FloatArray *f = this->givePrescribedVector(resolveIndx(tStep, 0));
298 for ( int inode : set->giveNodeList() ) {
299 DofManager *dman = d->giveDofManager(inode);
300 for ( auto &dofid : bc.giveDofIDs() ) {
301 Dof *dof = dman->giveDofWithID(dofid);
302 int peq = - dof->giveEqn(); // Note, only consider prescribed equations here
303 if ( peq > 0 ) {
304 f->at(peq) = bc.give(dof, VM_Total, tStep->giveTargetTime());
305 }
306 }
307 }
308}
309
310
311void
312PrimaryField :: update(ValueModeType mode, TimeStep *tStep, const FloatArray &vectorToStore, const UnknownNumberingScheme &s)
313{
314 if ( mode == VM_Total ) {
315 * this->giveSolutionVector(tStep) = vectorToStore;
316 } else {
317 OOFEM_ERROR("unsupported mode %s", __ValueModeTypeToString(mode));
318 }
319}
320
321double
322PrimaryField :: giveUnknownValue(Dof *dof, ValueModeType mode, TimeStep *tStep)
323{
324 int eq = dof->giveEqn();
325 if ( eq == 0 ) {
326 OOFEM_ERROR("invalid equation number (slave dof maybe?)");
327 }
328
329 if ( mode == VM_Total ) {
330 int indxm0 = this->resolveIndx(tStep, 0);
331 if ( eq > 0 )
332 return this->giveSolutionVector(indxm0)->at(eq);
333 else
334 return this->givePrescribedVector(indxm0)->at(-eq);
335 } else if ( mode == VM_Incremental ) {
336 int indxm0 = this->resolveIndx(tStep, 0);
337 int indxm1 = this->resolveIndx(tStep, -1);
338 if ( this->giveSolutionVector(indxm1)->giveSize() == 0 )
339 this->giveSolutionVector(indxm1)->resize(this->giveSolutionVector(indxm0)->giveSize());
340 if ( eq > 0 )
341 return ( this->giveSolutionVector(indxm0)->at(eq) - this->giveSolutionVector(indxm1)->at(eq) );
342 else
343 return ( this->givePrescribedVector(indxm0)->at(-eq) - this->givePrescribedVector(indxm1)->at(-eq) );
344 } else {
345 OOFEM_ERROR("unsupported mode");
346 }
347
348 // return 0.0;
349}
350
351int
352PrimaryField :: __evaluateAt(FloatArray &answer, DofManager *dman,
353 ValueModeType mode, TimeStep *tStep,
354 IntArray *dofId)
355{
356 if ( dman->giveDomain() == this->emodel->giveDomain(domainIndx) ) {
357 if ( dofId ) {
358 dman->giveUnknownVector(answer, * dofId, * this, mode, tStep, true);
359 return 0; // ok
360 } else { // all dofs requested
361 dman->giveCompleteUnknownVector(answer, mode, tStep);
362 return 0; // ok
363 }
364 } else {
365 return this->__evaluateAt(answer, dman->giveCoordinates(),
366 mode, tStep, dofId);
367 }
368}
369
370
371int
372PrimaryField :: __evaluateAt(FloatArray &answer, const FloatArray &coords,
373 ValueModeType mode, TimeStep *tStep,
374 IntArray *dofId)
375{
376 Domain *domain = emodel->giveDomain(domainIndx);
378
379#if 0
380 // locate background element
381 FloatArray lcoords, closest;
382 Element *bgelem = sl->giveElementClosestToPoint(lcoords, closest, coords);
383 if ( bgelem == NULL ) {
384 return 1;
385 }
386
387 if ( dofId ) {
388 bgelem->computeField(mode, tStep, lcoords, answer);
389 } else {
390 FloatArray field;
391 IntArray elemDofId;
392 bgelem->giveElementDofIDMask(elemDofId);
393 bgelem->computeField(mode, tStep, lcoords, field);
394 answer.resize( dofId->giveSize() );
395 answer.zero();
396 for ( int i = 1; i <= dofId->giveSize(); ++i ) {
397 int pos = elemDofId.findFirstIndexOf(dofId->at(i));
398 if ( pos > 0 ) {
399 answer.at(pos) = field.at(i);
400 }
401 }
402 }
403
404 return 0;
405#else
406 Element *bgelem;
407 // locate background element
408 if ( ( bgelem = sl->giveElementContainingPoint(coords) ) == NULL ) {
409 //_error("PrimaryField::evaluateAt: point not found in domain\n");
410 return 1;
411 }
412
414 if ( interface ) {
415 if ( dofId ) {
416 return interface->EIPrimaryFieldI_evaluateFieldVectorAt(answer, * this, coords, * dofId, mode, tStep);
417 } else { // use element default dof id mask
418 IntArray elemDofId;
419 bgelem->giveElementDofIDMask(elemDofId);
420 return interface->EIPrimaryFieldI_evaluateFieldVectorAt(answer, * this, coords, elemDofId, mode, tStep);
421 }
422 } else {
423 OOFEM_ERROR("background element does not support EIPrimaryFiledInterface");
424 }
425#endif
426}
427
428int
429PrimaryField :: evaluateAt(FloatArray &answer, const FloatArray &coords,
430 ValueModeType mode, TimeStep *tStep)
431{
432 return this->__evaluateAt(answer, coords, mode, tStep, NULL);
433}
434
435
436int
437PrimaryField :: evaluateAt(FloatArray &answer, DofManager *dman,
438 ValueModeType mode, TimeStep *tStep)
439{
440 return this->__evaluateAt(answer, dman, mode, tStep, NULL);
441}
442
443
445PrimaryField :: giveSolutionVector(TimeStep *tStep)
446{
447 return this->giveSolutionVector( resolveIndx(tStep, 0) );
448}
449
451PrimaryField :: giveSolutionVector(int i)
452{
453 if ( ( i < 1 ) || ( i > ( nHistVectors + 1 ) ) ) {
454 OOFEM_ERROR("index out of range");
455 }
456 return &solutionVectors[i-1];
457}
458
460PrimaryField :: givePrescribedVector(int i)
461{
462 if ( ( i < 1 ) || ( i > ( nHistVectors + 1 ) ) ) {
463 OOFEM_ERROR("index out of range");
464 }
465 return &prescribedVectors[i-1];
466}
467
468
469int
470PrimaryField :: resolveIndx(TimeStep *tStep, int shift)
471{
472 int tStepo = tStep->giveNumber();
473 int relPos = actualStepNumber - tStepo - shift;
474 if ( ( relPos >= 0 ) && ( relPos <= nHistVectors ) ) {
475 return ( actualStepIndx + relPos ) % ( nHistVectors + 1 ) + 1;
476 } else {
477 OOFEM_ERROR("History not available for relative step no. %d to step no. %d (actualStepNumber = %d)", shift, tStepo, actualStepNumber);
478 }
479
480 // return 0;
481}
482
483
484void
485PrimaryField :: advanceSolution(TimeStep *tStep)
486{
487 if ( actualStepNumber == tStep->giveNumber() ) {
488 // We're one the correct step already, no need to advance.
489 return;
490 }
491 if ( ( actualStepNumber >= 0 ) && ( actualStepNumber + 1 != tStep->giveNumber() ) ) {
492 OOFEM_ERROR("can not advance due to steps skipped");
493 }
494
496 actualStepNumber = tStep->giveNumber();
497 solStepList[actualStepIndx] = * tStep;
498 if ( nHistVectors > 1 ) {
499 // Copy over the old status to the new nodes
500 int curr = this->resolveIndx(tStep, 0);
501 int prev = this->resolveIndx(tStep, -1);
502 *this->giveSolutionVector(curr) = *this->giveSolutionVector(prev);
503 *this->givePrescribedVector(curr) = *this->givePrescribedVector(prev);
504 }
505}
506
507
508void
509PrimaryField :: saveContext(DataStream &stream)
510{
512
513 if ( !stream.write(actualStepNumber) ) {
515 }
516
517 if ( !stream.write(actualStepIndx) ) {
519 }
520
521 for ( const auto &vec : solutionVectors ) {
522 if ( ( iores = vec.storeYourself(stream) ) != CIO_OK ) {
523 THROW_CIOERR(iores);
524 }
525 }
526
527 for ( const auto &vec : prescribedVectors ) {
528 if ( ( iores = vec.storeYourself(stream) ) != CIO_OK ) {
529 THROW_CIOERR(iores);
530 }
531 }
532
533 for ( auto &step : solStepList ) {
534 step.saveContext(stream);
535 }
536}
537
538void
539PrimaryField :: restoreContext(DataStream &stream)
540{
542
543 if ( !stream.read(actualStepNumber) ) {
545 }
546
547 if ( !stream.read(actualStepIndx) ) {
549 }
550
551 for ( auto &vec : solutionVectors ) {
552 if ( ( iores = vec.restoreYourself(stream) ) != CIO_OK ) {
553 THROW_CIOERR(iores);
554 }
555 }
556
557 for ( auto &vec : prescribedVectors ) {
558 if ( ( iores = vec.storeYourself(stream) ) != CIO_OK ) {
559 THROW_CIOERR(iores);
560 }
561 }
562
563 for ( int i = 0; i <= nHistVectors; i++ ) {
565 solStepList[i].restoreContext(stream);
566 }
567}
568} // end namespace oofem
virtual double give(Dof *dof, ValueModeType mode, TimeStep *tStep)
virtual int read(int *data, std::size_t count)=0
Reads count integer values into array pointed by data.
virtual int write(const int *data, std::size_t count)=0
Writes count integer values from array pointed by data.
const FloatArray & giveCoordinates() const
Definition dofmanager.h:390
Dof * giveDofWithID(int dofID) const
Definition dofmanager.C:127
void giveCompleteUnknownVector(FloatArray &answer, ValueModeType mode, TimeStep *tStep)
Definition dofmanager.C:709
void giveUnknownVector(FloatArray &answer, const IntArray &dofMask, ValueModeType mode, TimeStep *tStep, bool padding=false)
Definition dofmanager.C:657
virtual int giveEqn()
Definition dof.h:407
SpatialLocalizer * giveSpatialLocalizer()
Definition domain.C:1255
InitialCondition * giveIc(int n)
Definition domain.C:258
Set * giveSet(int n)
Definition domain.C:366
std ::vector< std ::unique_ptr< DofManager > > & giveDofManagers()
Definition domain.h:427
std ::vector< std ::unique_ptr< GeneralBoundaryCondition > > & giveBcs()
Definition domain.h:349
DofManager * giveDofManager(int n)
Definition domain.C:317
GeneralBoundaryCondition * giveBc(int n)
Definition domain.C:246
std ::vector< std ::unique_ptr< Element > > & giveElements()
Definition domain.h:294
virtual void giveElementDofIDMask(IntArray &answer) const
Definition element.h:510
virtual void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer)
Definition element.h:520
Domain * giveDomain() const
Definition femcmpnn.h:97
virtual Interface * giveInterface(InterfaceType t)
Definition femcmpnn.h:181
Field(FieldType b=FieldType::FT_Unknown)
Definition field.h:95
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void subtract(const FloatArray &src)
Definition floatarray.C:320
virtual const IntArray & giveDofIDs() const
double give(ValueModeType mode, const FloatArray &coords)
int findFirstIndexOf(int value) const
Definition intarray.C:280
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
int resolveIndx(TimeStep *tStep, int shift)
FloatArray * givePrescribedVector(int)
std ::vector< FloatArray > prescribedVectors
void applyInitialCondition(InitialCondition &ic)
EngngModel * emodel
void storeDofManager(TimeStep *tStep, DofManager &dman)
virtual void applyBoundaryCondition(TimeStep *tStep)
virtual int __evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep, IntArray *dofId)
std ::vector< FloatArray > solutionVectors
std ::vector< TimeStep > solStepList
void readDofManager(TimeStep *tStep, DofManager &dman)
virtual FloatArray * giveSolutionVector(TimeStep *tStep)
const IntArray & giveNodeList()
Definition set.C:168
virtual Element * giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList=nullptr)=0
virtual Element * giveElementClosestToPoint(FloatArray &lcoords, FloatArray &closest, const FloatArray &coords, int region=0)=0
double giveTimeIncrement()
Returns solution step associated time increment.
Definition timestep.h:168
double giveTargetTime()
Returns target time.
Definition timestep.h:164
int giveNumber()
Returns receiver's number.
Definition timestep.h:144
TimeStep * givePreviousStep()
Returns pointer to previous solution step.
Definition timestep.C:132
#define THROW_CIOERR(e)
#define OOFEM_ERROR(...)
Definition error.h:79
FieldType
Physical type of field.
Definition field.h:64
@ EIPrimaryFieldInterfaceType
@ CIO_IOERR
General IO error.

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011