OOFEM 3.0
Loading...
Searching...
No Matches
dg.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 "dg.h"
36#include "timestep.h"
37#include "element.h"
38#include "dofmanager.h"
39#include "dof.h"
40#include "crosssection.h"
41#include "material.h"
42#include "dictionary.h"
43#include "verbose.h"
44#include "classfactory.h"
45#include "mathfem.h"
46#include "assemblercallback.h"
49#include "primaryfield.h"
50#include "maskedprimaryfield.h"
51#include "nrsolver.h"
52#include "activebc.h"
53#include "boundarycondition.h"
54#include "boundaryload.h"
55#include "outputmanager.h"
56#include "connectivitytable.h"
57#include "mpm.h"
58
59
60namespace oofem {
62
63ScalarAdvectionLhsAssembler :: ScalarAdvectionLhsAssembler(double alpha, double deltaT, Variable::VariableQuantity q) :
65{
66 this->q = q;
67}
68
69
70void ScalarAdvectionLhsAssembler :: matrixFromElement(FloatMatrix &answer, Element &el, TimeStep *tStep) const
71{
72 FloatMatrix contrib;
73 IntArray loc;
74 MPElement *e = dynamic_cast<MPElement*>(&el);
75 int ndofs = e->giveNumberOfDofs();
76 answer.resize(ndofs, ndofs);
77 answer.zero();
78
79 e->getLocalCodeNumbers (loc, q);
80
81 e->giveCharacteristicMatrix(contrib, MassMatrix, tStep);
82 if (contrib.isNotEmpty()) {
83 answer.assemble(contrib, loc, loc);
84 }
85 e->giveCharacteristicMatrix(contrib, StiffnessMatrix, tStep);
86 if (contrib.isNotEmpty()) {
87 contrib.times(this->deltaT/2.0);
88 answer.assemble(contrib, loc, loc);
89 }
90 // boundary terms
91 e->giveCharacteristicMatrix(contrib, InternalFluxVector, tStep);
92 if (contrib.isNotEmpty()) {
93 contrib.times(this->deltaT/2.0);
94 answer.assemble(contrib, loc, loc);
95 }
96}
97
98ScalarAdvectionRhsAssembler :: ScalarAdvectionRhsAssembler(double alpha, double deltaT, Variable::VariableQuantity q) :
100{
101 this->q = q;
102}
103
104
105void ScalarAdvectionRhsAssembler :: vectorFromElement(FloatArray &answer, Element &el, TimeStep *tStep, ValueModeType mode) const
106{
107 FloatMatrix contrib, rhsMatrix;
108 IntArray loc, dofids;
109 MPElement *e = dynamic_cast<MPElement*>(&el);
110 int ndofs = e->giveNumberOfDofs();
111 answer.resize(ndofs);
112 answer.zero();
113
114 rhsMatrix.resize(ndofs, ndofs);
115 rhsMatrix.zero();
116
117 e->getLocalCodeNumbers (loc, q);
118
119 e->giveCharacteristicMatrix(contrib, MassMatrix, tStep);
120 if (contrib.isNotEmpty()) {
121 rhsMatrix.add(contrib);
122 }
123 e->giveCharacteristicMatrix(contrib, StiffnessMatrix, tStep);
124 if (contrib.isNotEmpty()) {
125 contrib.times((-1.0)*this->deltaT/2.0);
126 rhsMatrix.add(contrib);
127 }
128 // boundary terms
129 e->giveCharacteristicMatrix(contrib, InternalFluxVector, tStep);
130 if (contrib.isNotEmpty()) {
131 contrib.times((-1.0)*this->deltaT/2.0);
132 rhsMatrix.add(contrib);
133 }
134 FloatArray help, rp;
135 e->computeVectorOf(VM_Total, tStep->givePreviousStep(), rp);
136
137 help.beProductOf(rhsMatrix, rp);
138 answer.assemble(help, loc);
139}
140
141
142void
144 EngngModel *emodel = this->giveDomain()->giveEngngModel();
145
146 fprintf( file, "%-8s%8d (%8d), Master:%d:\n", this->giveClassName(), this->giveLabel(), this->giveNumber(), master );
147 for ( Dof *dof: *this ) {
148 emodel->printDofOutputAt(file, dof, tStep);
149 }
150}
151
152
153DGProblem :: DGProblem(int i, EngngModel *_master = nullptr) : EngngModel(i, _master)
154{
155 ndomains = 1;
156}
157
158NumericalMethod *DGProblem :: giveNumericalMethod(MetaStep *mStep)
159{
160 if ( !nMethod ) {
161 if ( isParallel() ) {
162 if ( ( solverType == ST_Petsc ) || ( solverType == ST_Feti ) ) {
163 nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this);
164 }
165 } else {
166 nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this);
167 }
168 if ( !nMethod ) {
169 OOFEM_ERROR("linear solver creation failed for lstype %d", solverType);
170 }
171 }
172
173
174 return nMethod.get();
175}
176
177
178void
179DGProblem :: initializeFrom(InputRecord &ir)
180{
181 EngngModel :: initializeFrom(ir);
182
183 int val = SMT_Skyline;
185 this->sparseMtrxType = ( SparseMtrxType ) val;
186
187 if ( ir.hasField(_IFT_DGProblem_initt) ) {
189 }
190
193 } else if ( ir.hasField(_IFT_DGProblem_deltatfunction) ) {
195 } else if ( ir.hasField(_IFT_DGProblem_prescribedtimes) ) {
197 } else {
198 throw ValueInputException(ir, "none", "Time step not defined");
199 }
200
202 problemType = "sa"; // compatibility mode @TODO Remove default value
204 if (!((problemType == "sa")||(problemType == "tm"))) {
205 throw ValueInputException(ir, "none", "Problem type not recognized");
206 }
207 OOFEM_LOG_RELEVANT("DG: %s formulation\n", problemType.c_str());
208
210 field = std::make_unique<DofDistributedPrimaryField>(this, 1, FT_TransportProblemUnknowns, 2, this->alpha);
211
212 // read field export flag
213 exportFields.clear();
215 if ( exportFields.giveSize() ) {
216 FieldManager *fm = this->giveContext()->giveFieldManager();
217 for ( int i = 1; i <= exportFields.giveSize(); i++ ) {
218 if ( exportFields.at(i) == FT_Displacements ) {
219 FieldPtr _displacementField( new MaskedPrimaryField ( ( FieldType ) exportFields.at(i), this->field.get(), {D_u, D_v, D_w} ) );
220 fm->registerField( _displacementField, ( FieldType ) exportFields.at(i) );
221 } else if ( exportFields.at(i) == FT_Pressure ) {
222 FieldPtr _pressureField( new MaskedPrimaryField ( ( FieldType ) exportFields.at(i), this->field.get(), {P_f} ) );
223 fm->registerField( _pressureField, ( FieldType ) exportFields.at(i) );
224 }
225 }
226 }
228 preprocessFEM2DG = true;
229
232 if ( sets2preprocess.giveSize() != targetBoundaryNodeSets.giveSize() ) {
234 }
237 }
238
239}
240
241double DGProblem :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof)
242{
243 return this->field->giveUnknownValue(dof, mode, tStep);
244}
245
246
247double
248DGProblem :: giveDeltaT(int n)
249{
250 if ( this->dtFunction ) {
251 return this->giveDomain(1)->giveFunction(this->dtFunction)->evaluateAtTime(n);
252 } else if ( this->prescribedTimes.giveSize() > 0 ) {
253 return this->giveDiscreteTime(n) - this->giveDiscreteTime(n - 1);
254 } else {
255 return this->deltaT;
256 }
257}
258
259double
260DGProblem :: giveDiscreteTime(int iStep)
261{
262 if ( iStep > 0 && iStep <= this->prescribedTimes.giveSize() ) {
263 return ( this->prescribedTimes.at(iStep) );
264 } else if ( iStep == 0 ) {
265 return initT;
266 }
267
268 OOFEM_ERROR("invalid iStep");
269 return 0.0;
270}
271
272
273TimeStep *DGProblem :: giveNextStep()
274{
275 if ( !currentStep ) {
276 // first step -> generate initial step
277 currentStep = std::make_unique<TimeStep>( *giveSolutionStepWhenIcApply() );
278 }
279
280 double dt = this->giveDeltaT(currentStep->giveNumber()+1);
281 previousStep = std :: move(currentStep);
282 currentStep = std::make_unique<TimeStep>(*previousStep, dt);
283 currentStep->setIntrinsicTime(previousStep->giveTargetTime() + alpha * dt);
284 return currentStep.get();
285}
286
287
288TimeStep* DGProblem :: giveSolutionStepWhenIcApply(bool force)
289{
290 if ( master && (!force)) {
291 return master->giveSolutionStepWhenIcApply();
292 } else {
293 if ( !stepWhenIcApply ) {
294 double dt = this->giveDeltaT(1);
295 stepWhenIcApply = std::make_unique<TimeStep>(giveNumberOfTimeStepWhenIcApply(), this, 0, this->initT, dt, 0);
296 // The initial step goes from [-dt, 0], so the intrinsic time is at: -deltaT + alpha*dt
297 stepWhenIcApply->setIntrinsicTime(-dt + alpha * dt);
298 }
299
300 return stepWhenIcApply.get();
301 }
302}
303
304void
305DGProblem :: constructBoundaryEntities () {
306 // This method construct boundary entities of dimension nsd-1 (edges in 2D, surfaces in 3D) from the given mesh entities of dimension nsd.
307 // first loop over elements and their boundary entities
308 ConnectivityTable *ctable = this->giveDomain(1)->giveConnectivityTable();
309 // sets of processed boundary entities per element
310 std::vector<std::set<int>> processedBoundaryEntities;
311 processedBoundaryEntities.resize(this->giveDomain(1)->giveNumberOfElements());
312 Domain *domain = this->giveDomain(1);
313 // set maps to assist in generating boundary node sets
314 std::vector<std::unordered_multimap<int, int>> setsBoundaryEntities;
315 // boundary nodes sets to be generated
316 std::vector<std::set<int>> boundaryNodeSets;
317
318 int nnodes = domain->giveNumberOfDofManagers();
319 int nelems = domain->giveNumberOfElements();
320 int nodeNum = nnodes;
321 int elemNum = nelems;
322
323 Timer timer;
324 timer.startTimer();
325
326 // initialize setBoundaryEntities
327 setsBoundaryEntities.resize(this->sets2preprocess.giveSize());
328 boundaryNodeSets.resize(this->sets2preprocess.giveSize());
329 for (int iset = 1; iset<=sets2preprocess.giveSize(); iset++) {
330 const IntArray& bentities = domain->giveSet(sets2preprocess.at(iset))->giveBoundaryList();
331 for (int i = 1; i <= bentities.giveSize()/2; i++) {
332 setsBoundaryEntities[iset-1].insert({bentities.at(2*i-1), bentities.at(2*i)});
333 }
334 }
335
336 std::vector<IntArray> clonedElementNodes(nelems);
337 //OOFEM_LOG_INFO ("fem2DG: Decoupling elements\n");
338 for ( int ielem = 1; ielem<=nelems; ielem++) {
339 // decouple original (FE) elements
340 Element *e = domain->giveElement(ielem);
341 int numNodes = e->giveNumberOfDofManagers();
342 IntArray clonedNodes(numNodes);
343 for (int i = 1; i <= numNodes; i++) {
344 auto cnode = std::make_unique<ClonedDofManager>(++nodeNum, domain, e->giveDofManagerNumber(i));
345 cnode->setCoordinates( domain->giveDofManager(e->giveDofManagerNumber(i))->giveCoordinates() );
346 domain->resizeDofManagers(nodeNum);
347 domain->setDofManager(nodeNum, std::move(cnode));
348 clonedNodes.at(i) = nodeNum;
349 }
350 // store new element connectivity
351 clonedElementNodes.at(ielem-1)=clonedNodes;// e->setDofManagers(clonedNodes);
352 }
353 //OOFEM_LOG_INFO ("fem2DG: Constructing boundary entities\n");
354 for ( int ielem = 1; ielem<=nelems; ielem++) {
355 Element *e = domain->giveElement(ielem);
356 for ( int i = 1; i <= e->giveNumberOfBoundarySides(); i++ ) { // should rename as this is effectively number of boundary entities (edges or surfaces) depending on element dimension
357 if ( processedBoundaryEntities[e->giveNumber()-1].find(i) != processedBoundaryEntities[e->giveNumber()-1].end() ) {
358 continue; // edge already processed by neighbor element
359 }
360 IntArray bnodes, bnodesSorted, bclonednodes, neighbors;
361 bnodes = e->giveBoundaryNodes(i);
362 bclonednodes.resize(bnodes.giveSize());
363 for ( int j = 1; j <= bnodes.giveSize(); j++ ) {
364 bclonednodes.at(j) = clonedElementNodes.at(ielem-1).at(bnodes.at(j));
365 bnodes.at(j) = e->giveDofManager(bnodes.at(j))->giveNumber();
366 }
367 bnodesSorted = bnodes;
368 bnodesSorted.sort();
369 // now search element neighbors to find one sharing the same boundary nodes
370 ctable->giveElementsWithNodes(neighbors, bnodes);
371 if ( neighbors.giveSize() > 2 ) {
372 OOFEM_ERROR("More than two neighbors found for boundary entity (elem %d, boundary %d)", e->giveNumber(), i);
373 } else {
374 std::unique_ptr<DGBoundaryEntity> be = std::make_unique<DGBoundaryEntity>();
375 be->addElement(e->giveNumber(), i);
376 processedBoundaryEntities[e->giveNumber()-1].insert(i);
377 IntArray bentityNodes(bclonednodes); // nodes of boundary entity, initially bnodes followed by cloned or neighbor nodes
378 int neighborboundary=0; // identified neighbor boundary id
379
380 if ( neighbors.giveSize() == 1 ) {
381 //boundary entity not shared => we are on domain boundary
382 // create cloned nodes on boundary
383
384 for (int j = 1; j <= bnodes.giveSize(); j++)
385 {
386 auto cnode = std::make_unique<ClonedDofManager>(++nodeNum, domain, bnodes.at(j));
387 cnode->setCoordinates( domain->giveDofManager(bnodes.at(j))->giveCoordinates() );
388 domain->resizeDofManagers(nodeNum);
389 domain->setDofManager(nodeNum, std::move(cnode));
390 bentityNodes.followedBy(nodeNum, bnodes.giveSize());
391 }
392
393 // update boundary sets
394 for (int iset = 1; iset<=sets2preprocess.giveSize(); iset++) {
395 auto range = setsBoundaryEntities[iset-1].equal_range(e->giveNumber());
396 for (auto it = range.first; it != range.second; ++it) {
397 if (it->second == i) {
398 // add boundary nodes to target set
399 for (int k = 1; k <= bnodes.giveSize(); k++) {
400 boundaryNodeSets.at(iset-1).insert(bentityNodes.at(bnodes.giveSize()+k));
401 }
402 break; // only one boundary entity per element
403 }
404 }
405 }
406
407 } else if ( neighbors.giveSize() == 2 ) {
408 //boundary entity shared => we are on domain interior
409 int neighborelem = neighbors.at(1) == e->giveNumber() ? neighbors.at(2) : neighbors.at(1);
410 // neighbor boundary nodes
411 IntArray neighborBoundaryNodes;
412 IntArray neighborClonedBoundaryNodes;
413 for ( int j = 1; j <= this->giveDomain(1)->giveElement(neighborelem)->giveNumberOfBoundarySides(); j++ ) {
414 bool equal = true;
415 neighborBoundaryNodes = this->giveDomain(1)->giveElement(neighborelem)->giveBoundaryNodes(j);
416 int size = neighborBoundaryNodes.giveSize();
417 neighborClonedBoundaryNodes.resize(size);
418 for ( int k = 1; k <= size; k++ ) {
419 neighborClonedBoundaryNodes.at(k) = clonedElementNodes.at(neighborelem-1).at(neighborBoundaryNodes.at(k));
420 neighborBoundaryNodes.at(k) = this->giveDomain(1)->giveElement(neighborelem)->giveDofManager(neighborBoundaryNodes.at(k))->giveNumber();
421 }
422 // compare bnodes (sorted) with neighborBoundaryNodes
423 for ( int k = 1; k <= neighborBoundaryNodes.giveSize(); k++ ) {
424 if ( !bnodesSorted.findSorted(neighborBoundaryNodes.at(k))) {
425 equal = false;
426 break;
427 }
428 }
429 if ( equal) {
430 neighborboundary = j;
431 break;
432 }
433 }
434 if (neighborboundary) {
435 be->addElement(neighborelem, neighborboundary); // delete
436 processedBoundaryEntities[neighborelem-1].insert(neighborboundary);
437 // add nodes of neighbor element
438 for (int j = 1; j <= bnodes.giveSize(); j++)
439 {
440 bentityNodes.followedBy(neighborClonedBoundaryNodes.at(neighborBoundaryNodes.findFirstIndexOf(bnodes.at(j))), bnodes.giveSize());
441 }
442 } else {
443 OOFEM_ERROR("Boundary entity not found in neighbor element");
444 }
445 }
446 this->boundaryEntities.push_back(std::move(be));
447 // create boundary element
449 std::unique_ptr<Element> belem (this->CreateBoundaryElement(egt, ++elemNum, domain, bentityNodes));
450 domain->resizeElements(elemNum);
451 // @BP TODO fragile, replace by user defined values
452 belem->setCrossSection(1);
453 belem->setMaterial(1);
454 domain->setElement(elemNum, std::move(belem));
455
456 }
457 }
458 }
459 // finally make original elements decoupled
460 for ( int ielem = 1; ielem<=nelems; ielem++) {
461 Element *e = domain->giveElement(ielem);
462 e->setDofManagers(clonedElementNodes.at(ielem-1));
463 }
464 // update target boundary sets
465 for (int iset = 1; iset<=sets2preprocess.giveSize(); iset++) {
466 IntArray nodes(boundaryNodeSets.at(iset-1).size());
467 int counter = 1;
468 for (auto bnode: boundaryNodeSets.at(iset-1)) {
469 nodes.at(counter++)=bnode;
470 }
471 domain->giveSet(targetBoundaryNodeSets.at(iset))->clear();
472 domain->giveSet(targetBoundaryNodeSets.at(iset))->setNodeList(nodes);
473 }
474 // define target all node set
475 if ( targetAllNodeSet ) {
476 IntArray nodes(nodeNum);
477 for (int i = 1; i <= nodeNum; i++) {
478 nodes.at(i) = i;
479 }
480 domain->giveSet(targetAllNodeSet)->clear();
481 domain->giveSet(targetAllNodeSet)->setNodeList(nodes);
482 }
483 // define target all element set
484 if ( targetAllElementSet ) {
485 IntArray elements(elemNum);
486 for (int i = 1; i <= elemNum; i++) {
487 elements.at(i) = i;
488 }
490 domain->giveSet(targetAllElementSet)->setElementList(elements);
491 }
492 timer.stopTimer();
493 //OOFEM_LOG_INFO("fem2DG: generated %d interface elements, %d nodes cloned\n", elemNum-nelems, nodeNum-nnodes);
494 OOFEM_LOG_INFO("fem2DG: FE (%d nodes, %d elements) -> DG (%d nodes, %d elements)\n", nnodes, nelems, nodeNum, elemNum);
495 OOFEM_LOG_INFO("fem2DG: done in %.2fs\n", timer.getUtime());
496}
497
498
499std::unique_ptr< Element>
500DGProblem::CreateBoundaryElement( Element_Geometry_Type egt, int elemNum, Domain *domain, IntArray &bentityNodes) const
501{
502 std::unique_ptr<Element> belem;
503 switch (egt) {
504 case EGT_line_1:
505 belem = classFactory.createElement("sadgbline1", elemNum, domain);
506 break;
507 case EGT_quad_1:
508 belem = classFactory.createElement("sadgbquad1", elemNum, domain);
509 break;
510 default:
511 OOFEM_ERROR("Unknown boundary element geometry type");
512 }
513 belem->setDofManagers(bentityNodes);
514 return belem;
515}
516
517void
518DGProblem :: postInitialize()
519{
520 // set meta step bounds
521 int istep = this->giveNumberOfFirstStep(true);
522 for ( auto &metaStep: metaStepList ) {
523 istep = metaStep.setStepBounds(istep);
524 }
525
526 // initialize boundary entities
527 if ( preprocessFEM2DG ) {
529 }
530
531 for ( auto &domain: domainList ) {
532 domain->postInitialize();
533 }
534
535#if 0
536 if ( preprocessFEM2DG ) {
537 // print domain entities
538 for ( auto &dman: this->giveDomain(1)->dofManagerList ) {
539 ClonedDofManager *cdman = dynamic_cast<ClonedDofManager*>(dman.get());
540 Node *ndman = dynamic_cast<Node*>(dman.get());
541 std::string name;
542 int master=0;
543 if (ndman) {
544 name = "Node";
545 } else if (cdman) {
546 name = "ClonedNode";
547 master = cdman->giveMasterNumber();
548 }
549 printf("%10s %4d master %4d coords %6f %6f %6f dofs", name.c_str(), dman->giveNumber(), master, dman->giveCoordinate(1), dman->giveCoordinate(2), dman->giveCoordinate(3));
550 for ( Dof *dof: *dman ) {
551 printf(" %d", dof->giveDofID());
552 }
553 printf("\n");
554 }
555 for (auto &elem: this->giveDomain(1)->elementList) {
556 Element *e = elem.get();
557 printf("%8s %4d nodes", e->giveClassName(), e->giveNumber());
558 for ( int i = 1; i <= e->giveNumberOfDofManagers(); i++ ) {
559 printf(" %d", e->giveDofManager(i)->giveNumber());
560 }
561 printf("\n");
562 }
563
564 for (int iset =1; iset<= this->targetBoundaryNodeSets.giveSize(); iset++) {
565 Set *set = this->giveDomain(1)->giveSet(this->targetBoundaryNodeSets.at(iset));
566 printf("Set %d nodes", set->giveNumber());
567 for (int i = 1; i <= (set->giveNodeList()).giveSize(); i++) {
568 printf(" %d", (set->giveNodeList()).at(i));
569 }
570 printf("\n");
571 }
572 }
573#endif
574}
575
576
577
578void DGProblem :: solveYourselfAt(TimeStep *tStep)
579{
580 OOFEM_LOG_INFO( "\nSolving [step number %5d, time %e]\n", tStep->giveNumber(), tStep->giveTargetTime() );
581
582 Domain *d = this->giveDomain(1);
584
585 if ( tStep->isTheFirstStep() ) {
586 this->applyIC();
587
588 if ( !lhsMatrix ) {
589 lhsMatrix = classFactory.createSparseMtrx(sparseMtrxType);
590 lhsMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() );
591 }
592 }
593 OOFEM_LOG_INFO("Assembling system matrices\n");
594 lhsMatrix->zero();
596
597 // loop over boundary entities
598 // @BP instead using BoundaryEntity, we can set up MPMElement based boundary element representing the boundary entity,
599 // this would allow to use the same assembly code as for the interior
600 // the term to evaluate over the boundary is \int (f(s+, s-)\cdot (nv)) ds, where f is numerical flux. So this term has to be parametrized by numerical flux...
601
602 // @BP start of editing
604
605 field->advanceSolution(tStep);
606 field->initialize(VM_Total, tStep, solution, EModelDefaultEquationNumbering());
607
608 //FloatArray *pv = this->field->giveSolutionVector(tStep->givePreviousStep());
609 //FloatArray *v = this->field->giveSolutionVector(tStep);
610 FloatArray rhs(neq);
612 // add dirichlet boundary conditions
613 this->assembleDirichletBcRhsVector(rhs, tStep, VM_Total, EModelDefaultEquationNumbering(), d);
614 ConvergedReason status = this->nMethod->solve(*lhsMatrix, rhs, solution);
615 tStep->convergedReason = status;
616 this->updateSolution(solution, tStep, d); // ?
617 // @BP end of editing
618}
619
620
621void
622DGProblem :: updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d)
623{
625 this->field->update(VM_Total, tStep, solutionVector, EModelDefaultEquationNumbering());
628 this->field->applyBoundaryCondition(tStep);
629}
630
631
632void
633DGProblem :: updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm)
634{}
635
636
637void
638DGProblem :: updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d)
639{}
640
641
642void
643DGProblem :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d)
644{
645 OOFEM_ERROR("Unknown component");
646}
647
648
649void
650DGProblem :: applyIC()
651{
652 Domain *domain = this->giveDomain(1);
653 OOFEM_LOG_INFO("Applying initial conditions\n");
654
655 this->field->applyDefaultInitialCondition();
656
657 // set initial field IP values (needed by some nonlinear materials)
659 for ( auto &elem : domain->giveElements() ) {
660 Element *element = elem.get();
661 element->updateInternalState(s);
662 element->updateYourself(s);
663 }
664}
665
666
667bool
668DGProblem :: requiresEquationRenumbering(TimeStep *tStep)
669{
671 if ( tStep->isTheFirstStep() ) {
672 return true;
673 }
674 // Check if Dirichlet b.c.s has changed.
675 Domain *d = this->giveDomain(1);
676 for ( auto &gbc : d->giveBcs() ) {
677 ActiveBoundaryCondition *active_bc = dynamic_cast< ActiveBoundaryCondition * >(gbc.get());
678 BoundaryCondition *bc = dynamic_cast< BoundaryCondition * >(gbc.get());
679 // We only need to consider Dirichlet b.c.s
680 if ( bc || ( active_bc && ( active_bc->requiresActiveDofs() || active_bc->giveNumberOfInternalDofManagers() ) ) ) {
681 // Check of the dirichlet b.c. has changed in the last step (if so we need to renumber)
682 if ( gbc->isImposed(tStep) != gbc->isImposed(tStep->givePreviousStep()) ) {
683 return true;
684 }
685 }
686 }
687 return false;
688}
689
690int
691DGProblem :: forceEquationNumbering()
692{
693 this->lhsMatrix = nullptr;
694 this->rhsMatrix = nullptr;
695 return EngngModel :: forceEquationNumbering();
696}
697
698
699void
700DGProblem :: printOutputAt(FILE *file, TimeStep *tStep)
701{
702 if ( !this->giveDomain(1)->giveOutputManager()->testTimeStepOutput(tStep) ) {
703 return; // Do not print even Solution step header
704 }
705
706 EngngModel :: printOutputAt(file, tStep);
707}
708
709
710void
711DGProblem :: updateYourself(TimeStep *tStep)
712{
713 EngngModel :: updateYourself(tStep);
714}
715
716void
717DGProblem :: saveContext(DataStream &stream, ContextMode mode)
718{
719 EngngModel :: saveContext(stream, mode);
720 field->saveContext(stream);
721}
722
723
724void
725DGProblem :: restoreContext(DataStream &stream, ContextMode mode)
726{
727 EngngModel :: restoreContext(stream, mode);
728 field->restoreContext(stream);
729}
730
731
732int
733DGProblem :: giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep)
734{
735 return tStep->giveNumber() % 2;
736}
737
738
739int
740DGProblem :: requiresUnknownsDictionaryUpdate()
741{
742 return true;
743}
744
745int
746DGProblem :: checkConsistency()
747{
748 return EngngModel :: checkConsistency();
749}
750
751
752void
753DGProblem :: updateDomainLinks()
754{
755 EngngModel :: updateDomainLinks();
756 this->giveNumericalMethod( this->giveCurrentMetaStep() )->setDomain( this->giveDomain(1) );
757}
758
759
761{
762 /* Note: the current implementation uses MaskedPrimaryField, that is automatically updated with the model progress,
763 so the returned field always refers to active solution step.
764 */
765
766 if ( tStep != this->giveCurrentStep()) {
767 OOFEM_ERROR("Unable to return field representation for non-current time step");
768 }
769 if ( key == FT_Velocity ) {
770 return this->giveContext()->giveFieldManager()->giveField(FT_Velocity);
771 } else if ( key == FT_Pressure ) {
772 return std::make_shared<MaskedPrimaryField>( key, this->field.get(), IntArray{P_f} );
773 } else if ( key == FT_Temperature ) {
774 return std::make_shared<MaskedPrimaryField>( key, this->field.get(), IntArray{T_f} );
775 } else {
776 return FieldPtr();
777 }
778}
779
780
786void
788 const UnknownNumberingScheme &ns, Domain *d) const
789{
790 IntArray loc, dofids;
791 FloatArray rp1, rp, charVec, c1;
792 FloatMatrix ke,me,kte,m1;
793 FloatMatrix capacity;
794
795 int nelem = d->giveNumberOfElements();
796
797 for ( int ielem = 1; ielem <= nelem; ielem++ ) {
798 Element *element = d->giveElement(ielem);
799
800 element->giveElementDofIDMask(dofids);
801 element->computeVectorOfPrescribed(dofids, VM_Total, tStep, rp1);
802 element->computeVectorOfPrescribed(dofids, VM_Total, tStep->givePreviousStep(), rp);
803
804 if ( !rp.containsOnlyZeroes() || !rp1.containsOnlyZeroes() ) {
805 element->giveCharacteristicMatrix(ke, StiffnessMatrix, tStep);
806 element->giveCharacteristicMatrix(me, MassMatrix, tStep);
807 // internal flux (boundary elements)
808 element->giveCharacteristicMatrix(kte, InternalFluxVector, tStep);
809 if (ke.isNotEmpty() && kte.isNotEmpty()) {
810 ke.add(kte);
811 } else if (kte.isNotEmpty()) {
812 ke = kte;
813 }
814 element->giveLocationArray(loc, ns);
815
816 if ( !rp1.containsOnlyZeroes() ) {
817 m1 = ke;
818 m1.times(this->deltaT/2.0);
819 m1.add(me);
820 c1.beProductOf(m1, rp1);
821 c1.negated();
822 answer.assemble(c1, loc);
823 }
824/*
825 if ( !rp.containsOnlyZeroes() ) {
826 m1=ke;
827 m1.times((-1.0)*this->deltaT/2.0);
828 m1.add(me);
829 c1.beProductOf(m1, rp);
830 answer.assemble(c1, loc);
831 }
832*/
833 }
834 } // end element loop
835
836}
837
838
839} // end namespace oofem
#define REGISTER_EngngModel(class)
virtual bool requiresActiveDofs()
Definition activebc.h:151
const char * giveClassName() const override
Definition dg.h:113
void printOutputAt(FILE *file, TimeStep *tStep) override
Definition dg.C:143
int giveMasterNumber()
Definition dg.h:111
void giveElementsWithNodes(IntArray &answer, const IntArray &nodes)
double initT
Initial time from which the computation runs. Default is zero.
Definition dg.h:151
IntArray exportFields
Definition dg.h:160
double alpha
Definition dg.h:154
FloatArray prescribedTimes
Specified times where the problem is solved.
Definition dg.h:158
int dtFunction
Associated time function for time step increment.
Definition dg.h:156
TimeStep * giveSolutionStepWhenIcApply(bool force=false) override
Definition dg.C:288
SparseMtrxType sparseMtrxType
Definition dg.h:137
LinSystSolverType solverType
Definition dg.h:136
FieldPtr giveField(FieldType key, TimeStep *tStep) override
Definition dg.C:760
virtual void applyIC()
Definition dg.C:650
std ::unique_ptr< SparseLinearSystemNM > nMethod
Numerical method used to solve the problem.
Definition dg.h:148
std ::unique_ptr< DofDistributedPrimaryField > field
Definition dg.h:138
std::unique_ptr< Element > CreateBoundaryElement(Element_Geometry_Type egt, int elemNum, Domain *domain, IntArray &bentityNodes) const
Definition dg.C:500
bool keepTangent
Definition dg.h:159
bool preprocessFEM2DG
flag indicating whether the FEM input should be preprocessed to DG problem input (boundary entity gen...
Definition dg.h:164
int targetAllNodeSet
int target sets for all nodes and all elements
Definition dg.h:170
IntArray sets2preprocess
array of sets to process to generate boundary node sets
Definition dg.h:166
std ::vector< std::unique_ptr< DGBoundaryEntity > > boundaryEntities
Definition dg.h:185
NumericalMethod * giveNumericalMethod(MetaStep *mStep) override
Returns reference to receiver's numerical method.
Definition dg.C:158
FloatArray solution
Definition dg.h:143
double deltaT
Length of time step.
Definition dg.h:153
Variable::VariableQuantity unknownQuantity
Definition dg.h:134
double giveDeltaT(int n)
Definition dg.C:248
std ::unique_ptr< SparseMtrx > lhsMatrix
Definition dg.h:140
void updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) override
Definition dg.C:622
double giveDiscreteTime(int iStep)
Definition dg.C:260
void constructBoundaryEntities()
Definition dg.C:305
IntArray targetBoundaryNodeSets
array of target sets (same size as sets2preprocess) to store the generated boundary node sets
Definition dg.h:168
FloatArray eNorm
Definition dg.h:145
std::string problemType
identifies what problem to solve (UP, UPV, etc)
Definition dg.h:162
std ::unique_ptr< SparseMtrx > rhsMatrix
Definition dg.h:141
int targetAllElementSet
Definition dg.h:170
void assembleDirichletBcRhsVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode, const UnknownNumberingScheme &ns, Domain *d) const
Definition dg.C:787
int giveLabel() const
Definition dofmanager.h:516
const FloatArray & giveCoordinates() const
Definition dofmanager.h:390
void resizeDofManagers(int _newSize)
Resizes the internal data structure to accommodate space for _newSize dofManagers.
Definition domain.C:445
void resizeElements(int _newSize)
Resizes the internal data structure to accommodate space for _newSize elements.
Definition domain.C:446
void setElement(int i, std::unique_ptr< Element > obj)
Sets i-th component. The component will be further managed and maintained by domain object.
Definition domain.C:467
Set * giveSet(int n)
Definition domain.C:366
int giveNumberOfElements() const
Returns number of elements in domain.
Definition domain.h:463
int giveNumberOfDofManagers() const
Returns number of dof managers in domain.
Definition domain.h:461
std ::vector< std ::unique_ptr< GeneralBoundaryCondition > > & giveBcs()
Definition domain.h:349
DofManager * giveDofManager(int n)
Definition domain.C:317
Element * giveElement(int n)
Definition domain.C:165
EngngModel * giveEngngModel()
Definition domain.C:419
std ::vector< std ::unique_ptr< Element > > & giveElements()
Definition domain.h:294
void setDofManager(int i, std::unique_ptr< DofManager > obj)
Sets i-th component. The component will be further managed and maintained by domain object.
Definition domain.C:466
virtual void giveElementDofIDMask(IntArray &answer) const
Definition element.h:510
virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep)
Definition element.C:620
virtual int giveNumberOfDofs()
Definition element.h:239
virtual FEInterpolation * giveInterpolation() const
Definition element.h:648
virtual int giveNumberOfBoundarySides()
Returns number of boundaries (entities of element_dimension-1: points, edges, surfaces).
Definition element.C:1430
virtual void updateYourself(TimeStep *tStep)
Definition element.C:824
void computeVectorOfPrescribed(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:212
void setDofManagers(const IntArray &dmans)
Definition element.C:589
void giveLocationArray(IntArray &locationArray, const UnknownNumberingScheme &s, IntArray *dofIds=NULL) const
Definition element.C:429
virtual IntArray giveBoundaryNodes(int boundary) const
Definition element.C:904
void computeVectorOf(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:103
const char * giveClassName() const override
Definition element.h:1219
virtual int giveNumberOfDofManagers() const
Definition element.h:695
DofManager * giveDofManager(int i) const
Definition element.C:553
virtual void updateInternalState(TimeStep *tStep)
Definition element.h:769
int giveDofManagerNumber(int i) const
Definition element.h:609
FieldManager * giveFieldManager()
Definition engngm.h:141
int giveNumberOfTimeStepWhenIcApply()
Returns the time step number, when initial conditions should apply.
Definition engngm.h:787
std ::vector< std ::unique_ptr< Domain > > domainList
List of problem domains.
Definition engngm.h:217
virtual TimeStep * giveCurrentStep(bool force=false)
Definition engngm.h:717
virtual int giveNumberOfDomainEquations(int di, const UnknownNumberingScheme &num)
Definition engngm.C:452
virtual void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep)
Definition engngm.C:884
EngngModelContext * giveContext()
Context requesting service.
Definition engngm.h:1174
EngngModel(int i, EngngModel *_master=NULL)
Definition engngm.C:99
std ::unique_ptr< TimeStep > previousStep
Previous time step.
Definition engngm.h:243
MetaStep * giveCurrentMetaStep()
Returns current meta step.
Definition engngm.C:1900
int ndomains
Number of receiver domains.
Definition engngm.h:215
Domain * giveDomain(int n)
Definition engngm.C:1936
std ::unique_ptr< TimeStep > currentStep
Current time step.
Definition engngm.h:241
EngngModelTimer timer
E-model timer.
Definition engngm.h:279
std ::vector< MetaStep > metaStepList
List of problem metasteps.
Definition engngm.h:237
EngngModel * master
Master e-model; if defined receiver is in maintained (slave) mode.
Definition engngm.h:274
virtual int giveNumberOfFirstStep(bool force=false)
Definition engngm.h:763
bool isParallel() const
Returns true if receiver in parallel mode.
Definition engngm.h:1152
std ::unique_ptr< TimeStep > stepWhenIcApply
Solution step when IC (initial conditions) apply.
Definition engngm.h:239
void assembleVector(FloatArray &answer, TimeStep *tStep, const VectorAssembler &va, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms=NULL)
Definition engngm.C:1106
virtual const Element_Geometry_Type giveBoundaryGeometryType(int boundary) const =0
Domain * giveDomain() const
Definition femcmpnn.h:97
int giveNumber() const
Definition femcmpnn.h:104
void registerField(FieldPtr eField, FieldType key)
FieldPtr giveField(FieldType key)
bool containsOnlyZeroes() const
Definition floatarray.C:671
void assemble(const FloatArray &fe, const IntArray &loc)
Definition floatarray.C:616
void resize(Index s)
Definition floatarray.C:94
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void times(double f)
void add(const FloatMatrix &a)
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void zero()
Zeroes all coefficient of receiver.
bool isNotEmpty() const
Tests for empty matrix.
void assemble(const FloatMatrix &src, const IntArray &loc)
virtual int giveNumberOfInternalDofManagers()
Gives the number of internal dof managers.
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
void followedBy(const IntArray &b, int allocChunk=0)
Definition intarray.C:94
void resize(int n)
Definition intarray.C:73
int findSorted(int value) const
Definition intarray.C:293
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
Base class for elements based on mp (multi-physics) concept.
Definition mpm.h:282
virtual void getLocalCodeNumbers(IntArray &answer, const Variable::VariableQuantity q) const
Definition mpm.h:375
Variable::VariableQuantity q
Definition dg.h:80
Variable::VariableQuantity q
Definition dg.h:96
void clear()
Definition set.C:255
void setNodeList(IntArray newNodes)
Definition set.C:237
const IntArray & giveBoundaryList()
Definition set.C:160
void setElementList(IntArray newElements)
Definition set.C:231
const IntArray & giveNodeList()
Definition set.C:168
ConvergedReason convergedReason
Status of solution step (Converged,.
Definition timestep.h:120
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
bool isTheFirstStep()
Definition timestep.C:148
oofem::VariableQuantity VariableQuantity
Definition mpm.h:92
#define _IFT_DGProblem_initt
Definition dg.h:50
#define _IFT_DGProblem_prescribedtimes
Definition dg.h:53
#define _IFT_DGProblem_targetAllNodeSet
target sets to map allnodes and allelements
Definition dg.h:64
#define _IFT_DGProblem_exportFields
Fields to export for staggered problems.
Definition dg.h:56
#define _IFT_DGProblem_deltatfunction
Definition dg.h:52
#define _IFT_DGProblem_targetBoundaryNodeSets
Definition dg.h:62
#define _IFT_DGProblem_alpha
Definition dg.h:54
#define _IFT_DGProblem_problemType
Definition dg.h:57
#define _IFT_DGProblem_keepTangent
Fixes the tangent to be reused on each step.
Definition dg.h:55
#define _IFT_DGProblem_preprocessFEM2DG
Definition dg.h:58
#define _IFT_DGProblem_targetAllElementSet
Target sets to store all elements.
Definition dg.h:65
#define _IFT_DGProblem_deltat
Definition dg.h:51
#define _IFT_DGProblem_sets2preprocess
Sets to preprocess from FEM to DG problem.
Definition dg.h:61
#define _IFT_EngngModel_smtype
Definition engngm.h:92
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define OOFEM_LOG_INFO(...)
Definition logger.h:143
#define OOFEM_LOG_RELEVANT(...)
Definition logger.h:142
long ContextMode
Definition contextmode.h:43
FieldType
Physical type of field.
Definition field.h:64
FloatArrayF< N > assemble(const FloatArrayF< M > &x, int const (&c)[M])
Assemble components into zero matrix.
@ SMT_Skyline
Symmetric skyline.
ClassFactory & classFactory
std::shared_ptr< Field > FieldPtr
Definition field.h:78

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