OOFEM 3.0
Loading...
Searching...
No Matches
additivemanufacturingproblem.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
36#include "GCodeParser.h"
38#include "calculatorfunction.h"
39#include "initialcondition.h"
41#include "masterdof.h"
42#include "initialcondition.h"
43#include "load.h"
44#include "boundaryload.h"
45#include "boundarycondition.h"
46#include "node.h"
47#include "dofmanager.h"
49#include "dynamicinputrecord.h"
51#include "connectivitytable.h"
52#include "spatiallocalizer.h"
53#include "primaryfield.h"
54#include <vector>
55#include <chrono>
56#include <thread>
57
58#include "engngm.h"
59#include "fieldmanager.h"
60#include "timestep.h"
61#include "function.h"
62#include "metastep.h"
63#include "exportmodulemanager.h"
64#include "mathfem.h"
65#include "oofemtxtdatareader.h"
66#include "util.h"
67#include "verbose.h"
68#include "classfactory.h"
69#include "domain.h"
70#include "stepfunction.h"
71#include "depositedheatsource.h"
72#include "voxelvoffield.h"
73
74#include <stdlib.h>
75
76// #include "datarecord.h"
77
78
79#ifdef __OOFEG
80#include "oofeggraphiccontext.h"
81#endif
82
83namespace oofem {
85
87{
88 Domain *d = emodel->giveDomain( 1 );
89 int nodeId = cn.id;
90
91 std::unique_ptr<DofManager> dman( classFactory.createDofManager( "node", nodeId, d ) );
92 if ( !dman ) {
93 OOFEM_ERROR( "Couldn't create node %d\n", nodeId );
94 }
95
96 // Convert voxelGrid coordinates (in mm) to node coordinates (in m)
97 FloatArray coords = { cn.coords[0] / 1000, cn.coords[1] / 1000, cn.coords[2] / 1000 };
98
99 dman->setCoordinates( coords );
100 dman->setGlobalNumber( nodeId );
101
102
103 // Set for node
104 int nSetsBefore = d->giveNumberOfSets();
105 d->resizeSets( nSetsBefore + 1 );
106 int setId = nSetsBefore + 1;
107
108 std::unique_ptr<Set> set = std::make_unique<Set>( setId, d );
109 IntArray nodeIds = { nodeId };
110 set->setNumber( setId );
111 set->setNodeList( nodeIds );
112 d->setSet( setId, std::move( set ) );
113
114 // create a dof
115 Dof *dof = classFactory.createDof( DT_master, T_f, dman.get() );
116
117 // Initial condition
118 int nICBefore = d->giveNumberOfInitialConditions();
119 int ICId = nICBefore + 1;
120 d->resizeInitialConditions( ICId );
121 std::unique_ptr<InitialCondition> ic = std::make_unique<InitialCondition>( ICId, d );
123
124 Dictionary props = Dictionary();
125 props.add( 'u', this->printer.depositionTemperature );
126
128 IntArray dofIds = { T_f };
129 icInput.setField( dofIds, _IFT_InitialCondition_dofs );
130 icInput.setField( setId, _IFT_InitialCondition_set );
131 ic->initializeFrom( icInput );
132
133 d->setInitialCondition( ICId, std::move( ic ) );
134
135 if ( coords[2] <= 1e-12 ) {
136 // BC
137 int nBCBefore = d->giveNumberOfBoundaryConditions();
138 d->resizeBoundaryConditions( nBCBefore + 1 );
139 int bcId = nBCBefore + 1;
140
141 std::unique_ptr<GeneralBoundaryCondition> bc( classFactory.createBoundaryCondition( "BoundaryCondition", bcId, d ) );
142
145
146 FloatArray vals = { this->printer.heatBedTemperature };
147 IntArray dofs = { T_f };
151
152 bc->initializeFrom( myInput );
153
154 bc->setNumber( bcId );
155 bc->postInitialize();
156
157 d->setBoundaryCondition( bcId, std::move( bc ) );
158 // set bcid to the created dof
159 dof->setBcId( bcId ); // Note: slave dofs and such will simple ignore this.
160 } else {
161
162 // Fix node when its not activated
163 int nTFBefore = d->giveNumberOfFunctions();
164 d->resizeFunctions( nTFBefore + 1 );
165 std::unique_ptr<CalculatorFunction> tf = std::make_unique<CalculatorFunction>( nTFBefore + 1, d );
166
168 myInput.setField( "1-h(" + std::to_string( cn.timeActivated ) + ")", _IFT_CalculatorFunction_f );
169 tf->initializeFrom( myInput );
170
171 d->setFunction( nTFBefore + 1, std::move( tf ) );
172
173 int nBCBefore = d->giveNumberOfBoundaryConditions();
174 d->resizeBoundaryConditions( nBCBefore + 1 );
175 int bcId = nBCBefore + 1;
176
177 // add Dirichlet bc for newly added DOFs to restrict them before activation.
178 std::unique_ptr<GeneralBoundaryCondition> bc( classFactory.createBoundaryCondition( "BoundaryCondition", bcId, d ) );
179
183
184 FloatArray vals = { 235.0 }; // a dummy value
185 IntArray dofs = { T_f };
187 myInput2.setField( vals, _IFT_BoundaryCondition_values );
189
190 bc->initializeFrom( myInput2 );
191
192 bc->setNumber( bcId );
193 bc->postInitialize();
194
195 d->setBoundaryCondition( bcId, std::move( bc ) );
196 // set bcid to the created dof
197 dof->setBcId( bcId ); // Note: slave dofs and such will simple ignore this.
198 }
199
200
201 dman->appendDof( dof );
202 dman->postInitialize();
203 d->setDofManager( nodeId, std::move( dman ) );
204
205 return true;
206}
207
209{
210 try {
211 Domain *d = emodel->giveDomain( 1 );
212
213 // Add new element
214 int elId = cn.id;
215
216 std::unique_ptr<Element> elem( classFactory.createElement( "brick1ht", elId, d ) );
217 if ( !elem ) {
218 OOFEM_ERROR( "Couldn't create element %d\n", elId );
219 }
220
221 IntArray enodes = {
222 cn.nodes[0], cn.nodes[1], cn.nodes[2], cn.nodes[3],
223 cn.nodes[4], cn.nodes[5], cn.nodes[6], cn.nodes[7]
224 };
225
226 elem->setDofManagers( enodes );
227 elem->setGlobalNumber( elId );
228 elem->setCrossSection( 1 );
229 elem->setParallelMode( elementParallelMode::Element_local ); // TODO: WHY SOME ELEMENTS HAVE SET REMOTE????
230 elem->postInitialize(); // this is needed to allocate the integration point array
231
232 int nTFBefore = d->giveNumberOfFunctions();
233 d->resizeFunctions( nTFBefore + 1 );
234 std::unique_ptr<HeavisideTimeFunction> tf = std::make_unique<HeavisideTimeFunction>( nTFBefore + 1, d );
235
239 tf->initializeFrom( myInput );
240 elem->setActivityTimeFunctionNumber( nTFBefore + 1 );
241
242 d->setFunction( nTFBefore + 1, std::move( tf ) );
243 d->setElement( elId, std::move( elem ) );
244
245 // Add new node set
246 // Used to apply initial boundary condition to the new DOFs
247 int nSetsBefore = d->giveNumberOfSets();
248 d->resizeSets( nSetsBefore + 6 );
249
250 // Add 6 loads (1 per element face)
251 int nBCBefore = d->giveNumberOfBoundaryConditions();
252 d->resizeBoundaryConditions( nBCBefore + 6 );
253
254 for ( int i = 0; i < 6; i++ ) {
255 int setId = nSetsBefore + 1 + i;
256
257 std::unique_ptr<Set> set = std::make_unique<Set>( setId, d );
258 IntArray bounds = { elId, 1 + i };
259 set->setNumber( setId );
260 set->setBoundaryList( bounds );
261 // set->setNodeList(nNodeIds);
262 d->setSet( setId, std::move( set ) );
263
264 int bcid = nBCBefore + 1 + i;
265 std::unique_ptr<GeneralBoundaryCondition> bc( classFactory.createBoundaryCondition( "freeconstantsurfaceload", bcid, d ) );
266
270 Dictionary props = Dictionary();
271 props.add( 'a', this->printer.heatTransferFilmCoefficient ); // 97 == 'a'
272 myInput.setField( props, _IFT_BoundaryLoad_properties );
273
274 // todo: UNCOMMENT
275 FloatArray comps = { this->printer.chamberTemperature }; // ambient temp
276 myInput.setField( comps, _IFT_Load_components );
278
279 bc->initializeFrom( myInput );
280
281 bc->setNumber( bcid );
282 bc->postInitialize();
283
284 d->setBoundaryCondition( bcid, std::move( bc ) );
285 }
286
287#if 1
288 // add internal heat source to the element to account for deposited material temperature
289
290
291 nTFBefore = d->giveNumberOfFunctions();
292 std::unique_ptr<StepFunction> tf2 = std::make_unique<StepFunction>( nTFBefore + 1, d, cn.vofHistory );
293 //printf("Element %d: size of vof history: %d\n", elId, (int) cn.vofHistory.size());
294 d->resizeFunctions( nTFBefore + 1 );
295 d->setFunction( nTFBefore + 1, std::move( tf2 ) );
296
297
298 nBCBefore = d->giveNumberOfBoundaryConditions();
299 std::unique_ptr<DepositedHeatSource> load = std::make_unique<DepositedHeatSource>( nBCBefore+1, d, 0,
300 this->printer.depositedMaterialHeatPower, // power = specificHeat * density // @TODO: this should depend on material
301 this->printer.depositionTemperature, // deposition temperature
302 nTFBefore + 1 // deposited mass fraction function
303 );
304
305
306 d->resizeBoundaryConditions( nBCBefore + 1 );
307 d->setBoundaryCondition( nBCBefore+1, std::move( load ) );
308 d->giveElement( elId )->setBodyLoads({nBCBefore+1});
309#endif
310 } catch (...) {
311 OOFEM_ERROR( "Error when adding element %d\n", cn.id );
312 }
313}
314
316{
317 Domain *d = emodel->giveDomain( 1 );
318
319 int nodeId = cn.id;
320
321 // was already added?
322 if ( d->dofManagerList[cn.id - 1] != nullptr ) return false;
323
324 std::unique_ptr<DofManager> dman( classFactory.createDofManager( "node", nodeId, d ) );
325 if ( !dman ) {
326 OOFEM_ERROR( "Couldn't create node %d\n", nodeId );
327 }
328
329 FloatArray coords = { cn.coords[0] / 1000, cn.coords[1] / 1000, cn.coords[2] / 1000 };
330
331 /*DynamicInputRecord myInput = DynamicInputRecord(_IFT_Node_Name, nodeId);
332 IntArray mBCs = {1,1,1};
333 myInput.setField(mBCs, _IFT_DofManager_bc);
334 myInput.setField(coords, _IFT_Node_coords);
335 dman->initializeFrom(myInput);*/
336
337 dman->setCoordinates( coords );
338 dman->setGlobalNumber( nodeId );
339 // dman->appendDof( new MasterDof(dman.get(), D_u) );
340 // dman->appendDof( new MasterDof(dman.get(), D_v) );
341 // dman->appendDof( new MasterDof(dman.get(), D_w) );
342
343 // d->setDofManager(nodeId, std::move(dman));
344
345 // create a dof
346 Dof *dofU = classFactory.createDof( DT_master, D_u, dman.get() );
347 Dof *dofV = classFactory.createDof( DT_master, D_v, dman.get() );
348 Dof *dofW = classFactory.createDof( DT_master, D_w, dman.get() );
349
350 if ( coords[2] <= 1e-12 ) {
351 // Set for BC
352 int nSetsBefore = d->giveNumberOfSets();
353 int nBCBefore = d->giveNumberOfBoundaryConditions();
354 int bcId;
355
356 /*if (nSetsBefore > 0 ){
357 auto set = d->giveSet(nSetsBefore);
358 auto nodeList = set->giveSpecifiedNodeList();
359 nodeList.followedBy(nodeId,1);
360 set->setNodeList(nodeList);
361 bcId = nBCBefore;
362 }
363 else {*/
364 d->resizeSets( nSetsBefore + 1 );
365 int setId = nSetsBefore + 1;
366
367 std::unique_ptr<Set> set = std::make_unique<Set>( setId, d );
368 IntArray nodeIds = { nodeId };
369 set->setNumber( setId );
370 set->setNodeList( nodeIds );
371 d->setSet( setId, std::move( set ) );
372
373 // BC
374 // int nBCBefore = d->giveNumberOfBoundaryConditions();
375 d->resizeBoundaryConditions( nBCBefore + 1 );
376 bcId = nBCBefore + 1;
377
378 std::unique_ptr<GeneralBoundaryCondition> bc( classFactory.createBoundaryCondition( "BoundaryCondition", bcId, d ) );
379
382
383 FloatArray vals = { 0.0, 0.0, 0.0 };
384 IntArray dofs = { D_u, D_v, D_w };
388
389 bc->initializeFrom( myInput );
390
391 bc->setNumber( bcId );
392 bc->postInitialize();
393
394 d->setBoundaryCondition( bcId, std::move( bc ) );
395
396 //}
397
398 // set bcid to the created dof
399 dofU->setBcId( bcId ); // Note: slave dofs and such will simple ignore this.
400 dofV->setBcId( bcId ); // Note: slave dofs and such will simple ignore this.
401 dofW->setBcId( bcId ); // Note: slave dofs and such will simple ignore this.
402
403 } else {
404 // Set for node
405 int nSetsBefore = d->giveNumberOfSets();
406 d->resizeSets( nSetsBefore + 1 );
407 int setId = nSetsBefore + 1;
408
409 std::unique_ptr<Set> set = std::make_unique<Set>( setId, d );
410 IntArray nodeIds = { nodeId };
411 set->setNumber( setId );
412 set->setNodeList( nodeIds );
413 d->setSet( setId, std::move( set ) );
414
415 // Fix node when its not activated
416 int nTFBefore = d->giveNumberOfFunctions();
417 d->resizeFunctions( nTFBefore + 1 );
418 std::unique_ptr<CalculatorFunction> tf = std::make_unique<CalculatorFunction>( nTFBefore + 1, d );
419
421 myInput.setField( "1-h(" + std::to_string( cn.timeActivated ) + ")", _IFT_CalculatorFunction_f );
422 // myInput.setField("0", _IFT_CalculatorFunction_f);
423 // std::cout << "Node " <<nodeId << " activated at " << cn.activatedAt << std::endl;
424 // myInput.setField(1.0, _IFT_HeavisideTimeFunction_value);
425 tf->initializeFrom( myInput );
426 // elem->setActivityTimeFunctionNumber(nTFBefore+1);
427
428 d->setFunction( nTFBefore + 1, std::move( tf ) );
429
430 int nBCBefore = d->giveNumberOfBoundaryConditions();
431 d->resizeBoundaryConditions( nBCBefore + 1 );
432 int bcId = nBCBefore + 1;
433
434 std::unique_ptr<GeneralBoundaryCondition> bc( classFactory.createBoundaryCondition( "BoundaryCondition", bcId, d ) );
435
439
440 FloatArray vals = { 0.0, 0.0, 0.0 };
441 IntArray dofs = { D_u, D_v, D_w };
443 myInput2.setField( vals, _IFT_BoundaryCondition_values );
445
446 bc->initializeFrom( myInput2 );
447
448 bc->setNumber( bcId );
449 // bc->setIsImposedTimeFunctionNumber(nTFBefore+1);
450 bc->postInitialize();
451
452 d->setBoundaryCondition( bcId, std::move( bc ) );
453 // set bcid to the created dof
454 dofU->setBcId( bcId ); // Note: slave dofs and such will simple ignore this.
455 dofV->setBcId( bcId );
456 dofW->setBcId( bcId );
457 }
458
459 dman->appendDof( dofU );
460 dman->appendDof( dofV );
461 dman->appendDof( dofW );
462
463 d->setDofManager( nodeId, std::move( dman ) );
464 return true;
465}
466
467
469{
470 Domain *d = emodel->giveDomain( 1 );
471
472 // Add new element
473 int elId = cn.id;
474
475 // was already added?
476 if ( d->elementList[cn.id - 1] != nullptr ) return;
477
478 std::unique_ptr<Element> elem( classFactory.createElement( "LSpace", elId, d ) );
479 if ( !elem ) {
480 OOFEM_ERROR( "Couldn't create element %d\n", elId );
481 }
482
483 IntArray enodes = {
484 cn.nodes[0], cn.nodes[1], cn.nodes[2], cn.nodes[3],
485 cn.nodes[4], cn.nodes[5], cn.nodes[6], cn.nodes[7]
486 };
487
488 int nTFBefore = d->giveNumberOfFunctions();
489 d->resizeFunctions( nTFBefore + 1 );
490 std::unique_ptr<HeavisideTimeFunction> tf = std::make_unique<HeavisideTimeFunction>( nTFBefore + 1, d );
491
495 tf->initializeFrom( myInput );
496 elem->setActivityTimeFunctionNumber( nTFBefore + 1 );
497
498 d->setFunction( nTFBefore + 1, std::move( tf ) );
499
500 elem->setDofManagers( enodes );
501 elem->setGlobalNumber( elId );
502 elem->setCrossSection( 1 );
503 elem->setParallelMode( elementParallelMode::Element_local );
504 elem->postInitialize(); // this is needed to allocate the integration point array
505
506 d->setElement( elId, std::move( elem ) );
507}
508
509AdditiveManufacturingProblem ::AdditiveManufacturingProblem( int i, EngngModel *_master ) :
510 EngngModel( i, _master ),
511 adaptiveStepLength( false ),
512 minStepLength( 0. ),
513 maxStepLength( 0. ),
514 reqIterations( 0. ),
515 adaptiveStepSince( 0. ),
517 prevStepLength( 0. ),
519{
520 ndomains = 1; // domain is needed to store the time step function
521
522 dtFunction = 0;
523 stepMultiplier = 1.;
525
526 // fclose(stdout);
527 this->totalTimer.startTimer();
528}
529
530AdditiveManufacturingProblem ::~AdditiveManufacturingProblem()
531{
532 this->totalTimer.stopTimer();
533 OOFEM_LOG_INFO( "TOTAL TIME SOLVING: %.2fs\n", this->totalTimer.getUtime() );
534}
535
537int AdditiveManufacturingProblem ::instanciateYourself( DataReader &dr, InputRecord &ir, const char *dataOutputFileName, const char *desc )
538{
539 int result;
540 result = EngngModel ::instanciateYourself( dr, ir, dataOutputFileName, desc );
541 ir.finish();
542 // instanciate slave problems
543 result &= this->instanciateSlaveProblems();
544 return result;
545}
546
547int AdditiveManufacturingProblem ::instanciateDefaultMetaStep( InputRecord &ir )
548{
549 if ( timeDefinedByProb ) {
550 /* just set a nonzero number of steps;
551 * needed for instanciateDefaultMetaStep to pass; overall has no effect as time stepping is deteremined by slave
552 */
553 this->numberOfSteps = 1;
554 }
555 EngngModel ::instanciateDefaultMetaStep( ir );
556 // there are no slave problems initiated so far, the overall metaStep will defined in a slave problem instantiation
557 return 1;
558}
559
560int AdditiveManufacturingProblem ::instanciateSlaveProblems()
561{
562 // first instantiate master problem if defined
563 // EngngModel *timeDefProb = NULL;
564 emodelList.resize( inputStreamNames.size() );
565 if ( timeDefinedByProb ) {
567 std ::unique_ptr<EngngModel> prob( InstanciateProblem( dr, this->pMode, this->contextOutputMode, this ) );
568 // timeDefProb = prob.get();
569 emodelList[timeDefinedByProb - 1] = std ::move( prob );
570 }
571
572 for ( int i = 1; i <= (int)inputStreamNames.size(); i++ ) {
573 if ( i == timeDefinedByProb ) {
574 continue;
575 }
576
578 // the slave problem dictating time needs to have attribute master=NULL, other problems point to the dictating slave
579 std ::unique_ptr<EngngModel> prob( InstanciateProblem( dr, this->pMode, this->contextOutputMode, this ) );
580 emodelList[i - 1] = std ::move( prob );
581 }
582
583 return 1;
584}
585
586
587void AdditiveManufacturingProblem ::initializeFrom( InputRecord &ir )
588{
589 OOFEM_LOG_INFO( "Starting Additive Manufacturing solver\n" );
590
595
597
600
602 po.steps = { this->stepX, this->stepY, this->stepZ };
603 po.sizes = { (int)std::ceil( 250.0 / po.steps[0] ),
604 (int)std::ceil( 250.0 / po.steps[1] ),
605 (int)std::ceil( 250.0 / po.steps[2] ) };
614
615 auto pr = Printer( po );
616
617 OOFEM_LOG_INFO( "\n\nG-code file: %s\n", this->gCodeFilePath.c_str() );
618
619 GCodeParser parser;
620 std::vector<GCodeCommand> commands = parser.parseFile( this->gCodeFilePath );
621
622 double queue_size = 3;
623
624 for ( int i = 1; i < queue_size; i++ ) {
625 pr.addCommandToQueue( commands[i] );
626 }
627
628 std::size_t csize = commands.size();
629 if ( this->maxPrinterCommands > 0 && csize > (std::size_t)this->maxPrinterCommands ) {
630 csize = this->maxPrinterCommands;
631 OOFEM_LOG_INFO( "Limiting number of processed commands to %d\n", this->maxPrinterCommands );
632 }
633#ifdef DEBUG
634 //csize = 500;
635#endif
636 OOFEM_LOG_RELEVANT( "Processing g-code file\n");
637
638 double progress = 0;
639 printProgress(0);
640 for ( size_t i = 0; i < csize; i++ ) {
641 size_t j = i + queue_size;
642
643 pr.processCommand( commands[i] );
644
645 if ( j < commands.size() )
646 pr.addCommandToQueue( commands[j] );
647
648 pr.popCommandFromQueue();
649
650 double p = (double)(i+1) / (double)csize;
651 if ( int(100*p) > int(100*progress) ) {
652 progress = p;
653 printProgress(p);
654 }
655 }
656
657 this->printer = pr;
658 this->voxelVofField = std::make_shared<VoxelVOFField>();
659 this->voxelVofField->setGrid( &this->printer.getGrid() );
660 this->giveContext()->giveFieldManager()->registerField( voxelVofField, FieldType::FT_VOF );
661
662 OOFEM_LOG_INFO( "\nFinished G-code parsing\n\n" );
663 PrintStatistics ps = this->printer.getStatistics();
664 OOFEM_LOG_INFO("Total distance moved: %.2f mm\n", ps.distance_moved);
665 OOFEM_LOG_INFO("Total fillament extruded: %.2f mm\n", ps.filament_extruded);
666 OOFEM_LOG_INFO("Total print time (without cooling): %.2f s\n", ps.time);
667
668 pr.getGrid().writeVTK( "voxel_vof.vtk");
669
671 if ( numberOfSteps <= 0 ) {
672 throw ValueInputException( ir, _IFT_EngngModel_nsteps, "nsteps must be > 0" );
673 }
675 EngngModel ::initializeFrom( ir );
677 dtFunction = 0;
679 EngngModel ::initializeFrom( ir );
681 dtFunction = 0;
684 } else {
686 }
687
689 adaptiveStepLength = true;
690 this->minStepLength = 0.;
692 this->maxStepLength = 1.e32;
694 this->reqIterations = 1;
696 this->endOfTimeOfInterest = 1.e32;
698 this->adaptiveStepSince = 0.;
700 }
701
702
704 if ( stepMultiplier < 0 ) {
705 throw ValueInputException( ir, _IFT_AdditiveManufacturingProblem_stepmultiplier, "stepMultiplier must be > 0" );
706 }
707
708 // timeLag = 0.;
709 // IR_GIVE_OPTIONAL_FIELD(ir, timeLag, _IFT_AdditiveManufacturingProblem_timeLag);
710
711 inputStreamNames.resize( 2 );
713 inputStreamNames.resize( 3 );
714 }
715
718 if ( inputStreamNames.size() == 3 ) {
720 }
721
722
723 renumberFlag = true; // The staggered problem itself should always try to check if the sub-problems needs renumbering.
724
725 coupledModels.resize( 3 );
727
728
729 if ( dtFunction < 1 ) {
730 ndomains = 0;
731 domainNeqs.clear();
732 domainPrescribedNeqs.clear();
733 domainList.clear();
734 }
735
737
738 if ( suppressOutput ) {
739 printf( "Suppressing output.\n" );
740 } else {
741
742 if ( ( outputStream = fopen( this->dataOutputFileName.c_str(), "w" ) ) == NULL ) {
743 throw ValueInputException( ir, "None", "can't open output file: " + this->dataOutputFileName );
744 }
745
746 fprintf( outputStream, "%s", PRG_HEADER );
747 fprintf( outputStream, "\nStarting analysis on: %s\n", ctime( &this->startTime ) );
748 fprintf( outputStream, "%s\n", simulationDescription.c_str() );
749
750#ifdef __MPI_PARALLEL_MODE
751 if ( this->isParallel() ) {
752 fprintf( outputStream, "Problem rank is %d/%d on %s\n\n", this->rank, this->numProcs, this->processor_name );
753 }
754#endif
755 }
756}
757
758
759void AdditiveManufacturingProblem ::updateAttributes( MetaStep *mStep )
760{
761 auto &ir = mStep->giveAttributesRecord();
762
763 EngngModel ::updateAttributes( mStep );
764
765 // update attributes of slaves
766 for ( auto &emodel : emodelList ) {
767 emodel->updateAttributes( mStep );
768 }
769
770 if ( !timeDefinedByProb ) {
771 if ( ir.hasField( _IFT_AdditiveManufacturingProblem_deltat ) ) {
775 if ( stepMultiplier < 0 ) {
776 OOFEM_ERROR( "stepMultiplier must be > 0" )
777 }
778 } else if ( ir.hasField( _IFT_AdditiveManufacturingProblem_prescribedtimes ) ) {
780 }
781 }
782}
783
784Function *AdditiveManufacturingProblem ::giveDtFunction()
785// Returns the load-time function of the receiver.
786{
787 if ( !dtFunction ) {
788 return NULL;
789 }
790
791 return giveDomain( 1 )->giveFunction( dtFunction );
792}
793
794double
795AdditiveManufacturingProblem ::giveDeltaT( int n )
796{
797 if ( giveDtFunction() ) {
798 return giveDtFunction()->evaluateAtTime( n );
799 }
800
801 // in the first step the time increment is taken as the initial, user-specified value
802 if ( stepMultiplier != 1 && currentStep ) {
803 if ( currentStep->giveNumber() >= 2 ) {
804 return ( currentStep->giveTargetTime() * ( stepMultiplier ) );
805 }
806 }
807
808 if ( discreteTimes.giveSize() > 0 ) {
809 return this->giveDiscreteTime( n ) - this->giveDiscreteTime( n - 1 );
810 }
811
812 if ( adaptiveStepLength ) {
813 EngngModel *sp;
814 int nite = 1;
815 double adjustedDeltaT = deltaT;
816
817 if ( currentStep != NULL ) {
818 if ( currentStep->giveNumber() != 0 ) {
819 // return prescribed deltaT for times until time = adaptiveStepSince
820 // can be used for consecutive force loading applied in a specified number of steps
821 if ( !( currentStep->giveTargetTime() > this->adaptiveStepSince ) ) {
822 return adjustedDeltaT;
823 }
824
825 for ( int i = 1; i <= this->giveNumberOfSlaveProblems(); i++ ) {
826 sp = this->giveSlaveProblem( i );
827 nite = max( sp->giveCurrentNumberOfIterations(), nite );
828 }
829
830 if ( nite > reqIterations ) {
831 adjustedDeltaT = this->prevStepLength * reqIterations / nite;
832 } else {
833 adjustedDeltaT = this->prevStepLength * sqrt( sqrt( (double)reqIterations / (double)nite ) );
834 }
835
836 if ( adjustedDeltaT > maxStepLength ) {
837 adjustedDeltaT = maxStepLength;
838 }
839
840 if ( adjustedDeltaT < minStepLength ) {
841 adjustedDeltaT = minStepLength;
842 }
843 }
844 }
845
846 this->currentStepLength = adjustedDeltaT;
847
848 return adjustedDeltaT;
849 }
850
851 return deltaT;
852}
853
854double
855AdditiveManufacturingProblem ::giveDiscreteTime( int iStep )
856{
857 if ( ( iStep > 0 ) && ( iStep <= discreteTimes.giveSize() ) ) {
858 return ( discreteTimes.at( iStep ) );
859 }
860
861 if ( ( iStep == 0 ) && ( iStep <= discreteTimes.giveSize() ) ) {
862 return ( 0.0 );
863 }
864
865 OOFEM_ERROR( "invalid iStep" );
866 return 0.0;
867}
868
869TimeStep *
870AdditiveManufacturingProblem ::giveCurrentStep( bool force )
871{
872 if ( timeDefinedByProb ) {
873 return emodelList[timeDefinedByProb - 1].get()->giveCurrentStep( true );
874 } else {
875 return EngngModel ::giveCurrentStep();
876 }
877}
878
879TimeStep *
880AdditiveManufacturingProblem ::givePreviousStep( bool force )
881{
882 if ( timeDefinedByProb ) {
883 return emodelList[timeDefinedByProb - 1].get()->givePreviousStep( true );
884 } else {
885 return EngngModel ::givePreviousStep();
886 }
887}
888
889TimeStep *
890AdditiveManufacturingProblem ::giveSolutionStepWhenIcApply( bool force )
891{
892 if ( timeDefinedByProb ) {
893 return emodelList[timeDefinedByProb - 1].get()->giveSolutionStepWhenIcApply( true );
894 } else {
895 if ( !stepWhenIcApply ) {
896 int nFirst = giveNumberOfFirstStep();
897 // stepWhenIcApply = std::make_unique<TimeStep>(giveNumberOfTimeStepWhenIcApply(), this, 0, -giveDeltaT(nFirst), giveDeltaT(nFirst), 0); //previous version for [-dt, 0]
898 stepWhenIcApply = std::make_unique<TimeStep>( giveNumberOfTimeStepWhenIcApply(), this, 0, 0., giveDeltaT( nFirst ), 0 ); // now go from [0, dt]
899 }
900
901 return stepWhenIcApply.get();
902 }
903}
904
905
907AdditiveManufacturingProblem ::giveTimeControl()
908{
909 if ( !timeDefinedByProb ) {
910 return this;
911 } else { // time dictated by slave problem
912 return this->giveSlaveProblem( timeDefinedByProb );
913 }
914}
915
916
917int AdditiveManufacturingProblem ::giveNumberOfFirstStep( bool force )
918{
919 if ( timeDefinedByProb && !force ) {
920 return emodelList[timeDefinedByProb - 1].get()->giveNumberOfFirstStep( true );
921 } else {
922 return EngngModel ::giveNumberOfFirstStep( force );
923 }
924}
925
926
927TimeStep *
928AdditiveManufacturingProblem ::giveNextStep()
929{
930 int istep = this->giveNumberOfFirstStep();
931 double totalTime = 0;
932 StateCounterType counter = 1;
933
934 if ( !currentStep ) {
935 // first step -> generate initial step
936 currentStep = std::make_unique<TimeStep>( *giveSolutionStepWhenIcApply() );
937 }
938
939 double dt = this->giveDeltaT( currentStep->giveNumber() + 1 );
940 istep = currentStep->giveNumber() + 1;
941 totalTime = currentStep->giveTargetTime() + this->giveDeltaT( istep );
942 counter = currentStep->giveSolutionStateCounter() + 1;
943 previousStep = std ::move( currentStep );
944 currentStep = std::make_unique<TimeStep>( *previousStep, dt );
945
946 if ( ( totalTime >= this->endOfTimeOfInterest ) && this->adaptiveStepLength ) {
947 totalTime = this->endOfTimeOfInterest;
948 OOFEM_LOG_INFO( "\n==================================================================\n" );
949 OOFEM_LOG_INFO( "\nAdjusting time step length to: %lf \n\n", totalTime - previousStep->giveTargetTime() );
950 currentStep = std::make_unique<TimeStep>( istep, this, 1, totalTime, totalTime - previousStep->giveTargetTime(), counter );
951 this->numberOfSteps = istep;
952 } else {
953 if ( this->adaptiveStepLength ) {
954 OOFEM_LOG_INFO( "\n==================================================================\n" );
955 OOFEM_LOG_INFO( "\nAdjusting time step length to: %lf \n\n", totalTime - previousStep->giveTargetTime() );
956 }
957 currentStep = std::make_unique<TimeStep>( istep, this, 1, totalTime, totalTime - previousStep->giveTargetTime(), counter );
958 }
959
960 // time and dt variables are set eq to 0 for statics - has no meaning
961 return currentStep.get();
962}
963
964
965void AdditiveManufacturingProblem ::solveYourself()
966{
967 EngngModel *sp;
968 sp = giveTimeControl();
969
970 int smstep = 1, sjstep = 1;
971 this->timer.startTimer( EngngModelTimer ::EMTT_AnalysisTimer );
972
973 // Obtain eng models for TM and SM
974 TransientTransportProblem *em_tm = dynamic_cast<TransientTransportProblem *>( this->emodelList.at( 0 ).get() );
975 EngngModel *em_sm = this->emodelList.at( 1 ).get();
976
977 // Activate TM model
978 {
979 std::cout << "#3d printing TM elements " << printer.getGrid().active_elements() << std::endl;
980 std::cout << "#3d printing TM nodes " << printer.getGrid().active_nodes() << std::endl;
981
982 // Resize DOFs and Element lists
983 em_tm->giveDomain( 1 )->resizeDofManagers( printer.getGrid().active_nodes() );
984 em_tm->giveDomain( 1 )->resizeElements( printer.getGrid().active_elements() );
985
986 for ( auto &n : this->printer.getGrid().giveNodes() ) {
987 add_node_if_not_exists2( em_tm, n.second );
988 }
989
990 for ( auto &n : this->printer.getGrid().giveVoxels() ) {
991 add_element_if_not_exists2( em_tm, n.second );
992 }
993
994 if ( em_tm->giveExportModuleManager()->giveNumberOfModules() > 0 ) {
996 }
997 }
998
999 if ( !this->skipSM ) {
1000 std::cout << "#3d printing SM elements " << printer.getGrid().active_elements() << std::endl;
1001 std::cout << "#3d printing SM nodes " << printer.getGrid().active_nodes() << std::endl;
1002
1003 // Resize DOFs and Element lists
1004 em_sm->giveDomain( 1 )->resizeDofManagers( printer.getGrid().active_nodes() );
1005 em_sm->giveDomain( 1 )->resizeElements( printer.getGrid().active_elements() );
1006
1007 for ( auto &n : this->printer.getGrid().giveNodes() ) {
1008 add_sm_node_if_not_exists2( em_sm, n.second );
1009 }
1010
1011 for ( auto &n : this->printer.getGrid().giveVoxels() ) {
1012 add_sm_element_if_not_exists2( em_sm, n.second );
1013 }
1014
1015 if ( em_sm->giveExportModuleManager()->giveNumberOfModules() > 0 ) {
1017 }
1018 }
1019
1020 em_tm->giveDomain( 1 )->giveConnectivityTable()->reset();
1021
1022 if ( sp->giveCurrentStep() ) {
1023 smstep = sp->giveCurrentStep()->giveMetaStepNumber();
1024 sjstep = sp->giveMetaStep( smstep )->giveStepRelativeNumber( sp->giveCurrentStep()->giveNumber() ) + 1;
1025 }
1026
1027 for ( int imstep = smstep; imstep <= sp->giveNumberOfMetaSteps(); imstep++ ) { // loop over meta steps
1028 MetaStep *activeMStep = sp->giveMetaStep( imstep );
1029 // update state according to new meta step in all slaves
1030 this->initMetaStepAttributes( activeMStep );
1031
1032 int nTimeSteps = activeMStep->giveNumberOfSteps();
1033 for ( int jstep = sjstep; jstep <= nTimeSteps; jstep++ ) { // loop over time steps
1034 this->timer.startTimer( EngngModelTimer ::EMTT_SolutionStepTimer );
1035 this->timer.initTimer( EngngModelTimer ::EMTT_NetComputationalStepTimer );
1037 sp->giveNextStep();
1038
1039 // renumber equations if necessary. Ensure to call forceEquationNumbering() for staggered problems
1040 if ( this->requiresEquationRenumbering( sp->giveCurrentStep() ) ) {
1041 this->forceEquationNumbering();
1042 }
1043
1044 Timer timer;
1045 timer.startTimer();
1046 this->initializeYourself( sp->giveCurrentStep() );
1047 timer.stopTimer();
1048
1049 timer.startTimer();
1050 this->solveYourselfAt( sp->giveCurrentStep() );
1051 timer.stopTimer();
1052
1053 timer.startTimer();
1054 this->updateYourself( sp->giveCurrentStep() );
1055 timer.stopTimer();
1056
1057 timer.startTimer();
1058 this->terminate( sp->giveCurrentStep() );
1059 timer.stopTimer();
1060
1061 this->timer.stopTimer( EngngModelTimer ::EMTT_SolutionStepTimer );
1062 double _steptime = this->timer.getUtime( EngngModelTimer ::EMTT_SolutionStepTimer );
1063 OOFEM_LOG_INFO( "EngngModel info: user time consumed by solution step %d: %.2fs\n",
1064 sp->giveCurrentStep()->giveNumber(), _steptime );
1065
1066 if ( !suppressOutput ) {
1067 fprintf( this->giveOutputStream(), "\nUser time consumed by solution step %d: %.3f [s]\n\n",
1068 sp->giveCurrentStep()->giveNumber(), _steptime );
1069 }
1070
1071#ifdef __MPI_PARALLEL_MODE
1072 if ( loadBalancingFlag ) {
1073 this->balanceLoad( sp->giveCurrentStep() );
1074 }
1075
1076#endif
1077
1078 if ( ( sp->giveCurrentStep()->giveTargetTime() >= this->endOfTimeOfInterest ) && this->adaptiveStepLength ) {
1079 break;
1080 }
1081 }
1082 }
1083}
1084
1085void AdditiveManufacturingProblem ::solveYourselfAt( TimeStep *tStep )
1086{
1087#ifdef VERBOSE
1088 OOFEM_LOG_RELEVANT( "Solving [step number %5d, time %e]\n", tStep->giveNumber(), tStep->giveTargetTime() );
1089#endif
1090
1091 for ( auto &emodel : emodelList ) {
1092 emodel->solveYourselfAt( tStep );
1093 }
1094
1095 tStep->incrementStateCounter();
1096}
1097
1098int AdditiveManufacturingProblem ::forceEquationNumbering()
1099{
1100 int neqs = 0;
1101 for ( auto &emodel : emodelList ) {
1102 // renumber equations if necessary
1103 if ( emodel->requiresEquationRenumbering( emodel->giveCurrentStep() ) ) {
1104 neqs += emodel->forceEquationNumbering();
1105 }
1106 }
1107
1108 return neqs;
1109}
1110
1111void AdditiveManufacturingProblem ::updateYourself( TimeStep *tStep )
1112{
1113 if ( adaptiveStepLength ) {
1114 this->prevStepLength = this->currentStepLength;
1115 }
1116
1117 for ( auto &emodel : emodelList ) {
1118 emodel->updateYourself( tStep );
1119 }
1120
1121 EngngModel ::updateYourself( tStep );
1122}
1123
1124void AdditiveManufacturingProblem ::terminate( TimeStep *tStep )
1125{
1126 for ( auto &emodel : emodelList ) {
1127 emodel->terminate( tStep );
1128 }
1129}
1130
1131void AdditiveManufacturingProblem ::doStepOutput( TimeStep *tStep )
1132{
1133 for ( auto &emodel : emodelList ) {
1134 emodel->giveExportModuleManager()->doOutput( tStep );
1135 }
1136}
1137
1138
1139void AdditiveManufacturingProblem ::printOutputAt( FILE *file, TimeStep *tStep )
1140{
1141 // Subproblems handle the output themselves.
1142}
1143
1144
1145void AdditiveManufacturingProblem ::saveContext( DataStream &stream, ContextMode mode )
1146{
1147 EngngModel ::saveContext( stream, mode );
1148 for ( auto &emodel : emodelList ) {
1149 emodel->saveContext( stream, mode );
1150 }
1151}
1152
1153
1154void AdditiveManufacturingProblem ::restoreContext( DataStream &stream, ContextMode mode )
1155{
1156 EngngModel ::restoreContext( stream, mode );
1157 for ( auto &emodel : this->emodelList ) {
1158 emodel->restoreContext( stream, mode );
1159 }
1160}
1161
1162
1163EngngModel *
1164AdditiveManufacturingProblem ::giveSlaveProblem( int i )
1165{
1166 if ( ( i > 0 ) && ( i <= this->giveNumberOfSlaveProblems() ) ) {
1167 return this->emodelList[i - 1].get();
1168 } else {
1169 OOFEM_ERROR( "Undefined problem" );
1170 }
1171
1172 return NULL;
1173}
1174
1175
1176int AdditiveManufacturingProblem ::checkProblemConsistency()
1177{
1178 // check internal consistency
1179 // if success returns nonzero
1180 int result = 1;
1181 for ( auto &emodel : emodelList ) {
1182 result &= emodel->checkProblemConsistency();
1183 }
1184
1185#ifdef VERBOSE
1186 if ( result ) {
1187 OOFEM_LOG_DEBUG( "Consistency check: OK\n" );
1188 } else {
1189 VERBOSE_PRINTS( "Consistency check", "failed" )
1190 exit( 1 );
1191 }
1192
1193#endif
1194
1195 return result;
1196}
1197
1198void AdditiveManufacturingProblem ::updateDomainLinks()
1199{
1200 for ( auto &emodel : emodelList ) {
1201 emodel->updateDomainLinks();
1202 }
1203}
1204
1205void AdditiveManufacturingProblem ::setRenumberFlag()
1206{
1207 for ( auto &emodel : emodelList ) {
1208 emodel->setRenumberFlag();
1209 }
1210}
1211
1212#ifdef __OOFEG
1213void AdditiveManufacturingProblem ::drawYourself( oofegGraphicContext &gc )
1214{
1215 int ap = gc.getActiveProblemIndx();
1216 if ( ( ap > 0 ) && ( ap <= giveNumberOfSlaveProblems() ) ) {
1217 this->giveSlaveProblem( ap )->drawYourself( gc );
1218 }
1219}
1220
1221void AdditiveManufacturingProblem ::drawElements( oofegGraphicContext &gc )
1222{
1223 int ap = gc.getActiveProblemIndx();
1224 if ( ( ap > 0 ) && ( ap <= giveNumberOfSlaveProblems() ) ) {
1225 this->giveSlaveProblem( ap )->drawElements( gc );
1226 }
1227}
1228
1229void AdditiveManufacturingProblem ::drawNodes( oofegGraphicContext &gc )
1230{
1231 int ap = gc.getActiveProblemIndx();
1232 if ( ( ap > 0 ) && ( ap <= giveNumberOfSlaveProblems() ) ) {
1233 this->giveSlaveProblem( ap )->drawNodes( gc );
1234 }
1235}
1236#endif
1237} // end namespace oofem
#define _IFT_AdditiveManufacturingProblem_Printer_extrusionwidth
#define _IFT_AdditiveManufacturingProblem_prob1
#define _IFT_AdditiveManufacturingProblem_stepmultiplier
#define _IFT_AdditiveManufacturingProblem_stepy
#define _IFT_AdditiveManufacturingProblem_stepz
#define _IFT_AdditiveManufacturingProblem_reqiterations
#define _IFT_AdditiveManufacturingProblem_skipsm
#define _IFT_AdditiveManufacturingProblem_Printer_heatbedtemperature
#define _IFT_AdditiveManufacturingProblem_prob3
#define _IFT_AdditiveManufacturingProblem_coupling
#define _IFT_AdditiveManufacturingProblem_prob2
#define _IFT_AdditiveManufacturingProblem_adaptiveStepLength
#define _IFT_AdditiveManufacturingProblem_minvof
#define _IFT_AdditiveManufacturingProblem_maxsteplength
#define _IFT_AdditiveManufacturingProblem_endoftimeofinterest
#define _IFT_AdditiveManufacturingProblem_Printer_depositedmaterialheatpower
#define _IFT_AdditiveManufacturingProblem_Printer_heattransferfilmcoefficient
#define _IFT_AdditiveManufacturingProblem_Printer_chambertemperature
#define _IFT_AdditiveManufacturingProblem_maxprintercommands
#define _IFT_AdditiveManufacturingProblem_dtf
#define _IFT_AdditiveManufacturingProblem_deltat
#define _IFT_AdditiveManufacturingProblem_gcode
#define _IFT_AdditiveManufacturingProblem_prescribedtimes
#define _IFT_AdditiveManufacturingProblem_minsteplength
#define _IFT_AdditiveManufacturingProblem_adaptivestepsince
#define _IFT_AdditiveManufacturingProblem_Printer_layerheight
#define _IFT_AdditiveManufacturingProblem_Printer_depositiontemperature
#define _IFT_AdditiveManufacturingProblem_stepx
#define _IFT_AdditiveManufacturingProblem_timeDefinedByProb
#define _IFT_BoundaryCondition_Name
#define _IFT_BoundaryCondition_values
[ra,optional] Vector of prescribed values for each respective DOF.
#define _IFT_BoundaryLoad_properties
#define _IFT_BoundaryLoad_loadtype
#define _IFT_CalculatorFunction_f
#define _IFT_CalculatorFunction_Name
The GCodeParser class is used to parse G-code files.
Definition GCodeParser.h:16
std::vector< GCodeCommand > parseFile(const std::string &filename)
Parses a file and returns a vector of GCodeCommand objects.
Definition GCodeParser.h:23
The Printer class is used to process G-code commands and manage the printer state.
Definition Printer.h:77
#define REGISTER_EngngModel(class)
bool add_sm_node_if_not_exists2(EngngModel *emodel, const VoxelNode &cn)
FloatArray discreteTimes
Specified times where the problem is solved.
IntArray coupledModels
List of slave models to which this model is coupled.
double maxStepLength
adaptive time step length - maximum
double reqIterations
adaptive time step length - required (=optimum) number of iterations
double adaptiveStepSince
adaptive time step length applies after prescribed time
void add_element_if_not_exists2(EngngModel *emodel, Voxel &cn)
int giveNumberOfFirstStep(bool force=false) override
void initializeYourself(TimeStep *tStep) override
bool add_node_if_not_exists2(EngngModel *emodel, const VoxelNode &cn)
TimeStep * giveSolutionStepWhenIcApply(bool force=false) override
std ::vector< std ::unique_ptr< EngngModel > > emodelList
List of engineering models to solve sequentially.
int timeDefinedByProb
Optional parameter which specify problems to define load time functions.
void add_sm_element_if_not_exists2(EngngModel *emodel, Voxel &cn)
EngngModel * giveSlaveProblem(int i) override
Returns i-th slave problem.
std ::shared_ptr< VoxelVOFField > voxelVofField
int giveNumberOfSlaveProblems() override
Returns number of slave problems.
double minStepLength
adaptive time step length - minimum
int dtFunction
Associated time function for time step increment.
void reset()
reset receiver to an initial state (will force table update, when needed next time)
Pair * add(int aKey, double value)
Definition dictionary.C:79
virtual void setBcId(int bcId)
Overwrites the boundary condition id (0-inactive BC), intended for specific purposes such as coupling...
Definition dof.h:382
std ::vector< std ::unique_ptr< DofManager > > dofManagerList
Dof manager list.
Definition domain.h:126
void setSet(int i, std::unique_ptr< Set > obj)
Sets i-th component. The component will be further managed and maintained by domain object.
Definition domain.C:474
void resizeDofManagers(int _newSize)
Resizes the internal data structure to accommodate space for _newSize dofManagers.
Definition domain.C:445
int giveNumberOfBoundaryConditions() const
Returns number of boundary conditions in domain.
Definition domain.h:469
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
ConnectivityTable * giveConnectivityTable()
Definition domain.C:1240
void resizeBoundaryConditions(int _newSize)
Resizes the internal data structure to accommodate space for _newSize boundary conditions.
Definition domain.C:450
void resizeInitialConditions(int _newSize)
Resizes the internal data structure to accommodate space for _newSize initial conditions.
Definition domain.C:451
int giveNumberOfInitialConditions() const
Returns number of initial conditions in domain.
Definition domain.h:471
int giveNumberOfSets() const
Returns number of sets.
Definition domain.h:479
void setFunction(int i, std::unique_ptr< Function > obj)
Sets i-th component. The component will be further managed and maintained by domain object.
Definition domain.C:473
void resizeSets(int _newSize)
Resizes the internal data structure to accommodate space for _newSize sets.
Definition domain.C:453
Element * giveElement(int n)
Definition domain.C:165
void setBoundaryCondition(int i, std::unique_ptr< GeneralBoundaryCondition > obj)
Sets i-th component. The component will be further managed and maintained by domain object.
Definition domain.C:471
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
void resizeFunctions(int _newSize)
Resizes the internal data structure to accommodate space for _newSize load time functions.
Definition domain.C:452
std ::vector< std ::unique_ptr< Element > > elementList
Element list.
Definition domain.h:124
void setInitialCondition(int i, std::unique_ptr< InitialCondition > obj)
Sets i-th component. The component will be further managed and maintained by domain object.
Definition domain.C:472
int giveNumberOfFunctions() const
Returns number of load time functions in domain.
Definition domain.h:473
void setField(int item, InputFieldType id)
void setBodyLoads(const IntArray &bodyLoads)
Definition element.C:607
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 void preInitializeNextStep()
Does a pre-initialization of the next time step (implement if necessarry).
Definition engngm.h:749
int numProcs
Total number of collaborating processes.
Definition engngm.h:291
virtual int giveCurrentNumberOfIterations()
Definition engngm.h:579
virtual void balanceLoad(TimeStep *tStep)
Definition engngm.C:2238
int rank
Domain rank in a group of collaborating processes (0..groupSize-1).
Definition engngm.h:289
virtual TimeStep * giveCurrentStep(bool force=false)
Definition engngm.h:717
std::string dataOutputFileName
Path to output stream.
Definition engngm.h:248
ExportModuleManager * giveExportModuleManager()
Returns receiver's export module manager.
Definition engngm.h:791
std::string simulationDescription
Definition engngm.h:339
virtual TimeStep * giveNextStep()
Returns next time step (next to current step) of receiver.
Definition engngm.h:747
EngngModelContext * giveContext()
Context requesting service.
Definition engngm.h:1174
bool renumberFlag
Renumbering flag (renumbers equations after each step, necessary if Dirichlet BCs change).
Definition engngm.h:229
EngngModel(int i, EngngModel *_master=NULL)
Definition engngm.C:99
std ::unique_ptr< TimeStep > previousStep
Previous time step.
Definition engngm.h:243
char processor_name[PROCESSOR_NAME_LENGTH]
Processor name.
Definition engngm.h:296
int ndomains
Number of receiver domains.
Definition engngm.h:215
int numberOfSteps
Total number of time steps.
Definition engngm.h:219
Domain * giveDomain(int n)
Definition engngm.C:1936
std ::unique_ptr< TimeStep > currentStep
Current time step.
Definition engngm.h:241
bool loadBalancingFlag
If set to true, load balancing is active.
Definition engngm.h:307
FILE * giveOutputStream()
Returns file descriptor of output file.
Definition engngm.C:1994
time_t startTime
Solution start time.
Definition engngm.h:271
MetaStep * giveMetaStep(int i)
Returns the i-th meta step.
Definition engngm.h:773
EngngModelTimer timer
E-model timer.
Definition engngm.h:279
problemMode pMode
Domain mode.
Definition engngm.h:267
ContextOutputMode contextOutputMode
Domain context output mode.
Definition engngm.h:256
void initMetaStepAttributes(MetaStep *mStep)
Definition engngm.h:677
int giveNumberOfMetaSteps()
Return number of meta steps.
Definition engngm.h:771
bool suppressOutput
Flag for suppressing output to file.
Definition engngm.h:337
FILE * outputStream
Output stream.
Definition engngm.h:252
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
virtual bool requiresEquationRenumbering(TimeStep *tStep)
Definition engngm.h:915
IntArray domainPrescribedNeqs
Number of prescribed equations per domain.
Definition engngm.h:227
IntArray domainNeqs
Number of equations per domain.
Definition engngm.h:225
virtual void initialize()
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
virtual void finish(bool wrn=true)=0
Terminates the current record session and if the flag is true, warning is printed for unscanned token...
int giveStepRelativeNumber(int stepNumber)
Returns the step relative number to receiver.
Definition metastep.h:134
int giveNumberOfSteps()
Returns number of Steps it represent.
Definition metastep.h:118
InputRecord & giveAttributesRecord()
Returns e-model attributes.
Definition metastep.h:122
int giveNumberOfModules() const
M * giveModule(int num)
int giveMetaStepNumber()
Returns receiver's meta step number.
Definition timestep.h:150
void incrementStateCounter()
Updates solution state counter.
Definition timestep.h:213
double giveTargetTime()
Returns target time.
Definition timestep.h:164
int giveNumber()
Returns receiver's number.
Definition timestep.h:144
double getUtime()
Returns total user time elapsed in seconds.
Definition timer.C:105
void stopTimer()
Definition timer.C:77
#define _IFT_EngngModel_nsteps
Definition engngm.h:78
#define _IFT_EngngModel_suppressOutput
Definition engngm.h:94
#define OOFEM_ERROR(...)
Definition error.h:79
#define _IFT_FreeConstantSurfaceLoad_Name
#define _IFT_GeneralBoundaryCondition_set
#define _IFT_GeneralBoundaryCondition_timeFunct
#define _IFT_GeneralBoundaryCondition_dofs
#define _IFT_GeneralBoundaryCondition_isImposedTimeFunct
#define _IFT_HeavisideTimeFunction_value
#define _IFT_HeavisideTimeFunction_Name
#define _IFT_HeavisideTimeFunction_origin
#define _IFT_InitialCondition_Name
#define _IFT_InitialCondition_conditions
#define _IFT_InitialCondition_dofs
#define _IFT_InitialCondition_set
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define _IFT_Load_components
Definition load.h:47
#define OOFEM_LOG_INFO(...)
Definition logger.h:143
#define OOFEM_LOG_RELEVANT(...)
Definition logger.h:142
#define OOFEM_LOG_DEBUG(...)
Definition logger.h:144
long ContextMode
Definition contextmode.h:43
void printProgress(double percentage, const std::string &title, std::ostream &out)
Definition util.C:186
@ Element_local
Element is local, there are no contributions from other domains to this element.
Definition element.h:88
long StateCounterType
StateCounterType type used to indicate solution state.
FloatArrayF< N > max(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
std::unique_ptr< EngngModel > InstanciateProblem(DataReader &dr, problemMode mode, int contextFlag, EngngModel *_master, bool parallelFlag)
Definition util.C:153
ClassFactory & classFactory
oofem::oofegGraphicContext gc[OOFEG_LAST_LAYER]
OOFEM_EXPORT const char * PRG_HEADER
Definition oofemcfg.C:22
The PrintStatistics struct is used to track statistics of the printer.
Definition Printer.h:17
double distance_moved
Definition Printer.h:18
double time
Definition Printer.h:20
double filament_extruded
Definition Printer.h:19
The PrinterOptions struct is used to configure the Printer class.
Definition Printer.h:55
LayerHeightModel layerHeightModel
Definition Printer.h:61
double heatBedTemperature
Definition Printer.h:65
double depositedMaterialHeatPower
Definition Printer.h:68
double extrusionWidth
Definition Printer.h:63
double depositionTemperature
Definition Printer.h:64
std::array< int, 3 > sizes
Definition Printer.h:59
std::array< double, 3 > steps
Definition Printer.h:58
double heatTransferFilmCoefficient
Definition Printer.h:67
double layerHeight
Definition Printer.h:62
double chamberTemperature
Definition Printer.h:66
A struct to represent a 3D model.
Definition VoxelGrid.h:14
double coords[3]
Definition VoxelGrid.h:16
double timeActivated
Definition VoxelGrid.h:17
A struct to represent a single voxel.
Definition VoxelGrid.h:23
std::vector< std::tuple< double, double > > vofHistory
Definition VoxelGrid.h:27
int id
Definition VoxelGrid.h:24
double time_activated()
Get the time the voxel was activated.
Definition VoxelGrid.h:33
std::array< int, 8 > nodes
Definition VoxelGrid.h:25
#define VERBOSE_PRINTS(str, str1)
Definition verbose.h:55

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