OOFEM 3.0
Loading...
Searching...
No Matches
prescribedgradientbcperiodic.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 "dofiditem.h"
37#include "node.h"
38#include "dofmanager.h"
39#include "dof.h"
40#include "valuemodetype.h"
41#include "floatarray.h"
42#include "floatmatrix.h"
43#include "engngm.h"
44#include "node.h"
45#include "activedof.h"
46#include "masterdof.h"
47#include "classfactory.h"
48#include "sparsemtrxtype.h"
49#include "sparsemtrx.h"
50#include "sparselinsystemnm.h"
51#include "dynamicinputrecord.h"
52#include "domain.h"
53#include "spatiallocalizer.h"
54#include "feinterpol.h"
56#include "function.h"
57#include "timestep.h"
58#include "mathfem.h"
59
60namespace oofem {
62
63PrescribedGradientBCPeriodic :: PrescribedGradientBCPeriodic(int n, Domain *d) : ActiveBoundaryCondition(n, d), PrescribedGradientHomogenization(),
64 strain( new Node(1, d) )
65{
66 // The unknown volumetric strain
67 int nsd = d->giveNumberOfSpatialDimensions();
68 int components = nsd * nsd;
69 // The prescribed strains.
70 for ( int i = 0; i < components; i++ ) {
71 int dofid = d->giveNextFreeDofID();
72 strain_id.followedBy(dofid);
73 // Just putting in X_i id-items since they don't matter.
74 // These don't actually need to be active, they are masterdofs with prescribed values, its
75 // easier to just have them here rather than trying to make another Dirichlet boundary condition.
76 //strain->appendDof( new ActiveDof( strain.get(), (DofIDItem)dofid, this->giveNumber() ) );
77 strain->appendDof( new MasterDof(strain.get(), this->giveNumber(), 0, (DofIDItem)dofid ) );
78 }
79}
80
81
82PrescribedGradientBCPeriodic :: ~PrescribedGradientBCPeriodic()
83{
84}
85
86
87int PrescribedGradientBCPeriodic :: giveNumberOfInternalDofManagers()
88{
89 return 1;
90}
91
92
93DofManager *PrescribedGradientBCPeriodic :: giveInternalDofManager(int i)
94{
95 return this->strain.get();
96}
97
98
99void PrescribedGradientBCPeriodic :: findSlaveToMasterMap()
100{
101 FloatArray coord;
102 SpatialLocalizer *sl = this->domain->giveSpatialLocalizer();
103 //Set *masterSet = this->domain->giveSet(2);
104 const IntArray &nodes = this->domain->giveSet(this->set)->giveNodeList(); // Split into slave set and master set?
105 int nsd = jump.giveSize();
106 std :: vector< FloatArray > jumps;
107 // Construct all the possible jumps;
108 jumps.reserve((2 << (nsd-1)) - 1);
109 if ( nsd != 3 ) {
110 OOFEM_ERROR("Only 3d implemented yet!");
111 }
112 jumps.emplace_back(jump);
113 jumps.emplace_back(Vec3(jump.at(1), jump.at(2), 0.));
114 jumps.emplace_back(Vec3(jump.at(1), 0., jump.at(3)));
115 jumps.emplace_back(Vec3(0., jump.at(2), jump.at(3)));
116 jumps.emplace_back(Vec3(jump.at(1), 0., 0.));
117 jumps.emplace_back(Vec3(0., jump.at(2), 0.));
118 jumps.emplace_back(Vec3(0., 0., jump.at(3)));
119
120 this->slavemap.clear();
121 for ( int inode : nodes ) {
122 Node *masterNode = nullptr;
123 Node *node = this->domain->giveNode(inode);
124 const auto &masterCoord = node->giveCoordinates();
125 //printf("node %d\n", node->giveLabel()); masterCoord.printYourself();
126 // The difficult part, what offset to subtract to find the master side;
127 for ( const FloatArray &testJump : jumps ) {
128 coord.beDifferenceOf(masterCoord, testJump);
129 masterNode = sl->giveNodeClosestToPoint(coord, fabs(jump.at(1))*1e-5);
130 if ( masterNode ) {
131 //printf("Found master (%d) to node %d (distance = %e)\n", masterNode->giveNumber(), node->giveNumber(),
132 // distance(*masterNode->giveCoordinates(), coord));
133 break;
134 }
135 }
136 if ( masterNode ) {
137 this->slavemap.insert({node->giveNumber(), masterNode->giveNumber()});
138 } else {
139 OOFEM_ERROR("Couldn't find master node!");
140 }
141 }
142}
143
144
145int PrescribedGradientBCPeriodic :: giveNumberOfMasterDofs(ActiveDof *dof)
146{
147 if ( this->isStrainDof(dof) ) {
148 return 1;
149 }
150 return this->giveDomain()->giveNumberOfSpatialDimensions() + 1;
151}
152
153
154Dof *PrescribedGradientBCPeriodic :: giveMasterDof(ActiveDof *dof, int mdof)
155{
156 if ( this->isStrainDof(dof) ) {
157 return nullptr;
158 }
159 if ( mdof == 1 ) {
160 int node = this->slavemap[dof->giveDofManager()->giveNumber()];
161 //printf("dofid = %d, slave node = %d, master node = %d\n", dof->giveDofID(),dof->giveDofManager()->giveNumber(), node );
162 //this->domain->giveDofManager(node)->printYourself();
163 return this->domain->giveDofManager(node)->giveDofWithID(dof->giveDofID());
164 } else {
165 DofIDItem dofid = dof->giveDofID();
166 const auto &coords = dof->giveDofManager()->giveCoordinates();
167 int nsd = coords.giveSize();
168 if ( dofid == D_u || dofid == V_u ) {
169 return this->strain->giveDofWithID(strain_id[nsd*(mdof-2)]);
170 } else if ( dofid == D_v || dofid == V_v ) {
171 return this->strain->giveDofWithID(strain_id[nsd*(mdof-2)+1]);
172 } else /* if ( dofid == D_u || dofid == V_u ) */ {
173 return this->strain->giveDofWithID(strain_id[nsd*(mdof-2)+2]);
174 }
175 }
176}
177
178
179void PrescribedGradientBCPeriodic :: computeField(FloatArray &sigma, TimeStep *tStep)
180{
182 EngngModel *emodel = this->giveDomain()->giveEngngModel();
183 FloatArray tmp, sig_tmp;
184 int npeq = strain_id.giveSize();
185 // sigma = residual (since we use the slave dofs) = f_ext - f_int
186 sig_tmp.resize(npeq);
187 sig_tmp.zero();
188 emodel->assembleVector(sig_tmp, tStep, InternalForceAssembler(), VM_Total, pnum, this->domain);
189 tmp.resize(npeq);
190 tmp.zero();
191 emodel->assembleVector(tmp, tStep, ExternalForceAssembler(), VM_Total, pnum, this->domain);
192 sig_tmp.subtract(tmp);
193 // Divide by the RVE-volume
194 sig_tmp.times(1.0 / ( this->domainSize(this->giveDomain(), this->set) + this->domainSize(this->giveDomain(), this->masterSet) ));
195
196 sigma.resize(sig_tmp.giveSize());
197 if ( sig_tmp.giveSize() == 9 ) {
198 sigma.assemble(sig_tmp, {1, 9, 8, 6, 2, 7, 5, 4, 3});
199 } else if ( sig_tmp.giveSize() == 4 ) {
200 sigma.assemble(sig_tmp, {1, 4, 3, 2});
201 } else {
202 sigma = sig_tmp;
203 }
204}
205
206
207void PrescribedGradientBCPeriodic :: computeTangent(FloatMatrix &E, TimeStep *tStep)
208{
211 EngngModel *rve = this->giveDomain()->giveEngngModel();
213 std :: unique_ptr< SparseLinearSystemNM > solver( classFactory.createSparseLinSolver( ST_Petsc, this->domain, this->domain->giveEngngModel() ) ); // = rve->giveLinearSolver();
214 SparseMtrxType stype = solver->giveRecommendedMatrix(true);
215 std :: unique_ptr< SparseMtrx > Kff( classFactory.createSparseMtrx( stype ) );
216 std :: unique_ptr< SparseMtrx > Kfp( classFactory.createSparseMtrx( stype ) );
217 std :: unique_ptr< SparseMtrx > Kpp( classFactory.createSparseMtrx( stype ) );
218
219 Kff->buildInternalStructure(rve, this->domain->giveNumber(), fnum);
220 Kfp->buildInternalStructure(rve, this->domain->giveNumber(), fnum, pnum);
221 Kpp->buildInternalStructure(rve, this->domain->giveNumber(), pnum);
222 rve->assemble(*Kff, tStep, TangentAssembler(TangentStiffness), fnum, this->domain);
223 rve->assemble(*Kfp, tStep, TangentAssembler(TangentStiffness), fnum, pnum, this->domain);
224 rve->assemble(*Kpp, tStep, TangentAssembler(TangentStiffness), pnum, this->domain);
225
226 int neq = Kfp->giveNumberOfRows();
227 int nsd = this->domain->giveNumberOfSpatialDimensions();
228 int ncomp = nsd * nsd;
229
230 FloatMatrix grad_pert(ncomp, ncomp), rhs, sol(neq, ncomp);
231 grad_pert.resize(ncomp, ncomp); // In fact, npeq should most likely equal ndev
232 grad_pert.beUnitMatrix();
233
234 // Compute the solution to each of the pertubation of eps
235 Kfp->times(grad_pert, rhs);
236 solver->solve(*Kff, rhs, sol);
237
238 // Compute the solution to each of the pertubation of eps
239 FloatMatrix E_tmp;
240 Kfp->timesT(sol, E_tmp); // Assuming symmetry of stiffness matrix
241 // This is probably always zero, but for generality
242 FloatMatrix tmpMat;
243 Kpp->times(grad_pert, tmpMat);
244 E_tmp.subtract(tmpMat);
245 E_tmp.times( - 1.0 / ( this->domainSize(this->giveDomain(), this->set) + this->domainSize(this->giveDomain(), this->masterSet) ));
246
247 E.resize(E_tmp.giveNumberOfRows(), E_tmp.giveNumberOfColumns());
248 if ( nsd == 3 ) {
249 if ( E_tmp.giveNumberOfRows() == 6 ) {
250 E.assemble(E_tmp, {1, 6, 5, 6, 2, 4, 5, 4, 3});
251 } else {
252 E.assemble(E_tmp, {1, 9, 8, 6, 2, 7, 5, 4, 3});
253 }
254 } else if ( nsd == 2 ) {
255 E.assemble(E_tmp, {1, 4, 3, 2});
256 } else {
257 E = E_tmp;
258 }
259}
260
261
262void PrescribedGradientBCPeriodic :: computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs)
263{
264 DofManager *master = this->domain->giveDofManager(this->slavemap[dof->giveDofManager()->giveNumber()]);
265 const auto &coords = dof->giveDofManager()->giveCoordinates();
266 const auto &masterCoords = master->giveCoordinates();
267
268 FloatArray dx;
269 dx.beDifferenceOf(coords, masterCoords);
270
271 int nsd = dx.giveSize(); // Number of spatial dimensions
272
273 masterContribs.resize(nsd + 1);
274
275 masterContribs.at(1) = 1.; // Master dof is always weight 1.0
276 for ( int i = 1; i <= dx.giveSize(); ++i ) {
277 masterContribs.at(i+1) = dx.at(i);
278 }
279}
280
281
282double PrescribedGradientBCPeriodic :: giveUnknown(double val, ValueModeType mode, TimeStep *tStep, ActiveDof *dof)
283{
284 DofManager *master = this->domain->giveDofManager(this->slavemap[dof->giveDofManager()->giveNumber()]);
285 DofIDItem id = dof->giveDofID();
286 const auto &coords = dof->giveDofManager()->giveCoordinates();
287 const auto &masterCoords = master->giveCoordinates();
288 FloatArray dx, uM;
289 dx.beDifferenceOf(coords, masterCoords);
290
291 int ind;
292 if ( id == D_u || id == V_u || id == P_f || id == T_f ) {
293 ind = 1;
294 } else if ( id == D_v || id == V_v ) {
295 ind = 2;
296 } else { /*if ( id == D_w || id == V_w )*/ // 3D only:
297 ind = 3;
298 }
299
300 FloatMatrix grad(3, 3);
301 for ( int i = 0; i < this->strain_id.giveSize(); ++i ) {
302 Dof *dof = this->strain->giveDofWithID(strain_id[i]);
303 grad(i % 3, i / 3) = dof->giveUnknown(mode, tStep);
304 }
305 uM.beProductOf(grad, dx); // The "jump" part of the unknown ( u^+ = [[u^M]] + u^- )
306
307 return val + uM.at(ind);
308}
309
310
311double PrescribedGradientBCPeriodic :: giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep, ActiveDof *dof)
312{
313 if ( this->isStrainDof(dof) ) {
314 int ind = strain_id.findFirstIndexOf(dof->giveDofID()) - 1;
315 return this->mGradient(ind % 3, ind / 3) * this->giveTimeFunction()->evaluateAtTime(tStep->giveTargetTime());
316 }
317
318 DofManager *master = this->domain->giveDofManager(this->slavemap[dof->giveDofManager()->giveNumber()]);
319 double val = master->giveDofWithID(dof->giveDofID())->giveUnknown(field, mode, tStep);
320 return this->giveUnknown(val, mode, tStep, dof);
321}
322
323
324double PrescribedGradientBCPeriodic :: giveUnknown(ValueModeType mode, TimeStep *tStep, ActiveDof *dof)
325{
326 if ( this->isStrainDof(dof) ) {
327 int ind = strain_id.findFirstIndexOf(dof->giveDofID()) - 1;
328 return this->mGradient(ind % 3, ind / 3) * this->giveTimeFunction()->evaluateAtTime(tStep->giveTargetTime());
329 }
330
331 DofManager *master = this->domain->giveDofManager(this->slavemap[dof->giveDofManager()->giveNumber()]);
332
333 if ( mode == VM_Incremental ) {
334 double val = master->giveDofWithID(dof->giveDofID())->giveUnknown(mode, tStep);
335 return this->giveUnknown(val, mode, tStep, dof);
336 }
337 double val = master->giveDofWithID(dof->giveDofID())->giveUnknown(mode, tStep);
338 return this->giveUnknown(val, mode, tStep, dof);
339}
340
341
342bool PrescribedGradientBCPeriodic :: isPrimaryDof(ActiveDof *dof)
343{
344 return this->isStrainDof(dof);
345}
346
347
348double PrescribedGradientBCPeriodic :: giveBcValue(Dof *dof, ValueModeType mode, TimeStep *tStep)
349{
350 if ( this->isStrainDof(dof) ) {
351 int index = strain_id.findFirstIndexOf(dof->giveDofID()) - 1;
352 return this->mGradient( index % 3, index / 3 ) * this->giveTimeFunction()->evaluateAtTime(tStep->giveTargetTime());;
353 }
354 OOFEM_ERROR("Has no prescribed value from bc.");
355 //return 0.0;
356}
357
358
359bool PrescribedGradientBCPeriodic :: hasBc(Dof *dof, TimeStep *tStep)
360{
361 return this->isStrainDof(dof);
362}
363
364
365bool PrescribedGradientBCPeriodic :: isStrainDof(Dof *dof)
366{
367 return this->strain.get() == dof->giveDofManager();
368}
369
370
371void PrescribedGradientBCPeriodic :: initializeFrom(InputRecord &ir)
372{
373 ActiveBoundaryCondition :: initializeFrom(ir);
375
378}
379
380
381void PrescribedGradientBCPeriodic :: giveInputRecord(DynamicInputRecord &input)
382{
383 ActiveBoundaryCondition :: giveInputRecord(input);
384 PrescribedGradientHomogenization :: giveInputRecord(input);
387}
388
389
390void PrescribedGradientBCPeriodic :: postInitialize()
391{
392 this->findSlaveToMasterMap();
393}
394} // end namespace oofem
#define E(a, b)
#define REGISTER_BoundaryCondition(class)
ActiveBoundaryCondition(int n, Domain *d)
Definition activebc.h:71
const FloatArray & giveCoordinates() const
Definition dofmanager.h:390
Dof * giveDofWithID(int dofID) const
Definition dofmanager.C:127
DofIDItem giveDofID() const
Definition dof.h:276
virtual double giveUnknown(ValueModeType mode, TimeStep *tStep)=0
DofManager * giveDofManager() const
Definition dof.h:123
int giveNextFreeDofID(int increment=1)
Definition domain.C:1519
int giveNumberOfSpatialDimensions()
Returns number of spatial dimensions.
Definition domain.C:1137
void setField(int item, InputFieldType id)
virtual void assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAssembler &ma, const UnknownNumberingScheme &s, Domain *domain)
Definition engngm.C:889
void assembleVector(FloatArray &answer, TimeStep *tStep, const VectorAssembler &va, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms=NULL)
Definition engngm.C:1106
Domain * giveDomain() const
Definition femcmpnn.h:97
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
int giveNumber() const
Definition femcmpnn.h:104
void assemble(const FloatArray &fe, const IntArray &loc)
Definition floatarray.C:616
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void beDifferenceOf(const FloatArray &a, const FloatArray &b)
Definition floatarray.C:403
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void subtract(const FloatArray &src)
Definition floatarray.C:320
void times(double s)
Definition floatarray.C:834
void times(double f)
int giveNumberOfColumns() const
Returns number of columns of receiver.
int giveNumberOfRows() const
Returns number of rows of receiver.
void subtract(const FloatMatrix &a)
int set
Set number for boundary condition to be applied to.
double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep, ActiveDof *dof) override
virtual Node * giveNodeClosestToPoint(const FloatArray &coords, double maxDist)=0
double giveTargetTime()
Returns target time.
Definition timestep.h:164
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
ClassFactory & classFactory
static FloatArray Vec3(const double &a, const double &b, const double &c)
Definition floatarray.h:607
#define _IFT_PrescribedGradientBCPeriodic_jump
#define _IFT_PrescribedGradientBCPeriodic_masterSet

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