OOFEM 3.0
Loading...
Searching...
No Matches
zznodalrecoverymodel.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 "timestep.h"
37#include "element.h"
38#include "dofmanager.h"
39#include "gausspoint.h"
40#include "integrationrule.h"
41#include "feinterpol.h"
42#include "mathfem.h"
43#include "feinterpol.h"
44#include "error.h"
45#include "engngm.h"
46#include "classfactory.h"
47
48#include <sstream>
49#include <set>
50
51#ifdef __MPI_PARALLEL_MODE
52 #include "problemcomm.h"
53 #include "communicator.h"
54#endif
55
56#define ZZNRM_ZERO_VALUE 1.e-12
57
58namespace oofem {
59REGISTER_NodalRecoveryModel(ZZNodalRecoveryModel, NodalRecoveryModel :: NRM_ZienkiewiczZhu);
60
61ZZNodalRecoveryModel :: ZZNodalRecoveryModel(Domain *d) : NodalRecoveryModel(d)
62{ }
63
64ZZNodalRecoveryModel :: ~ZZNodalRecoveryModel()
65{ }
66
67int
68ZZNodalRecoveryModel :: recoverValues(Set elementSet, InternalStateType type, TimeStep *tStep)
69{
70 int nnodes = domain->giveNumberOfDofManagers();
71 IntArray regionNodalNumbers(nnodes);
72 // following variable is for better error reporting only
73 std :: set< int >unresolvedDofMans;
74 // IntArray loc;
75 FloatArray lhs, nn, sol;
76 FloatMatrix rhs, nsig;
77
78
79 if ( this->valType == type && this->stateCounter == tStep->giveSolutionStateCounter() ) {
80 return 1;
81 }
82
83#ifdef __MPI_PARALLEL_MODE
84 if ( this->domain->giveEngngModel()->isParallel() ) {
85 this->initCommMaps();
86 }
87#endif
88
89 // clear nodal table
90 this->clear();
91
92 int elemNodes;
93 int regionValSize;
94 int regionDofMans;
95
96 // loop over elements and determine local region node numbering and determine and check nodal values size
97 if ( this->initRegionNodeNumbering(regionNodalNumbers, regionDofMans, elementSet) == 0 ) {
98 return 0;
99 }
100
101 regionValSize = 0;
102 lhs.resize(regionDofMans);
103 lhs.zero();
104 IntArray elements = elementSet.giveElementList();
105 // assemble element contributions
106 for ( int i = 1; i <= elements.giveSize(); i++ ) {
107 int ielem = elements.at(i);
109 Element *element = domain->giveElement(ielem);
110
111 if ( element->giveParallelMode() != Element_local ) {
112 continue;
113 }
114
115 // If an element doesn't implement the interface, it is ignored.
116 if ( ( interface = static_cast< ZZNodalRecoveryModelInterface * >( element->giveInterface(ZZNodalRecoveryModelInterfaceType) ) ) == NULL ) {
117 //abort();
118 continue;
119 }
120
121
122 // ask element contributions
123 if (!interface->ZZNodalRecoveryMI_computeNValProduct(nsig, type, tStep)) {
124 // skip element contribution if value type recognized by element
125 continue;
126 }
127 interface->ZZNodalRecoveryMI_computeNNMatrix(nn, type);
128
129 // assemble contributions
130 elemNodes = element->giveNumberOfDofManagers();
131
132 if ( regionValSize == 0 ) {
133 regionValSize = nsig.giveNumberOfColumns();
134 rhs.resize(regionDofMans, regionValSize);
135 rhs.zero();
136 if ( regionValSize == 0 ) {
137 OOFEM_LOG_RELEVANT( "ZZNodalRecoveryModel :: unknown size of InternalStateType %s\n", __InternalStateTypeToString(type) );
138 }
139 } else if ( regionValSize != nsig.giveNumberOfColumns() ) {
140 nsig.resize(regionDofMans, regionValSize);
141 nsig.zero();
142 OOFEM_LOG_RELEVANT( "ZZNodalRecoveryModel :: changing size of for InternalStateType %s. New sized results ignored (this shouldn't happen).\n", __InternalStateTypeToString(type) );
143 }
144
145 //loc.resize ((elemNodes+elemSides)*regionValSize);
146 int eq = 1;
147 for ( int elementNode = 1; elementNode <= elemNodes; elementNode++ ) {
148 int node = element->giveDofManager(elementNode)->giveNumber();
149 lhs.at( regionNodalNumbers.at(node) ) += nn.at(eq);
150 for ( int j = 1; j <= regionValSize; j++ ) {
151 rhs.at(regionNodalNumbers.at(node), j) += nsig.at(eq, j);
152 }
153
154 eq++;
155 }
156 } // end assemble element contributions
157
158#ifdef __MPI_PARALLEL_MODE
159 if ( this->domain->giveEngngModel()->isParallel() ) {
160 this->exchangeDofManValues(lhs, rhs, regionNodalNumbers);
161 }
162#endif
163
164 sol.resize(regionDofMans * regionValSize);
165 sol.zero();
166
167 bool missingDofManContribution = false;
168 unresolvedDofMans.clear();
169 // solve for recovered values of active region
170 for ( int i = 1; i <= regionDofMans; i++ ) {
171 int eq = ( i - 1 ) * regionValSize;
172 for ( int j = 1; j <= regionValSize; j++ ) {
173 // rhs will be overriden by recovered values
174 if ( fabs( lhs.at(i) ) > ZZNRM_ZERO_VALUE ) {
175 sol.at(eq + j) = rhs.at(i, j) / lhs.at(i);
176 } else {
177 missingDofManContribution = true;
178 unresolvedDofMans.insert( regionNodalNumbers.at(i) );
179 sol.at(eq + j) = 0.0;
180 }
181 }
182 }
183
184 // update recovered values
185 this->updateRegionRecoveredValues(regionNodalNumbers, regionValSize, sol);
186
187 if ( missingDofManContribution ) {
188 std :: ostringstream msg;
189 int i = 0;
190 for ( int dman: unresolvedDofMans ) {
191 msg << this->domain->giveDofManager(dman)->giveLabel() << ' ';
192 if ( ++i > 20 ) {
193 break;
194 }
195 }
196 if ( i > 20 ) {
197 msg << "...";
198 }
199 OOFEM_WARNING("InternalStateType %s: some values of some dofmanagers undetermined (in global numbers) \n[%s] for ", __InternalStateTypeToString(type), msg.str().c_str());
200 }
201
202
203 this->valType = type;
204 this->stateCounter = tStep->giveSolutionStateCounter();
205 return 1;
206}
207
208
209bool
210ZZNodalRecoveryModelInterface :: ZZNodalRecoveryMI_computeNValProduct(FloatMatrix &answer, InternalStateType type,
211 TimeStep *tStep)
212{ // evaluates N^T sigma over element volume
213 // N(nsigma, nsigma*nnodes)
214 // Definition : sigmaVector = N * nodalSigmaVector
215 FloatArray stressVector, n;
216 FEInterpolation *interpol = element->giveInterpolation();
217 IntegrationRule *iRule = element->giveDefaultIntegrationRulePtr();
218 bool success = true;
219
220 answer.clear();
221 for ( GaussPoint *gp: *iRule ) {
222 double dV = element->computeVolumeAround(gp);
223 //this-> computeStressVector(stressVector, gp, tStep);
224 if ( !element->giveIPValue(stressVector, gp, type, tStep) ) {
225 success = false;
226 continue;
227 }
228
229 interpol->evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(element) );
230 answer.plusDyadUnsym(n, stressVector, dV);
231
232 // help.beTProductOf(n,stressVector);
233 // answer.add(help.times(dV));
234 }
235 return success;
236}
237
238void
239ZZNodalRecoveryModelInterface :: ZZNodalRecoveryMI_computeNNMatrix(FloatArray &answer, InternalStateType type)
240{
241 //
242 // Returns NTN matrix (lumped) for Zienkiewicz-Zhu
243 // The size of N mtrx is (nstresses, nnodes*nstreses)
244 // Definition : sigmaVector = N * nodalSigmaVector
245 //
246 //double volume = 0.0;
247 FloatMatrix fullAnswer;
248 FloatArray n;
249 FEInterpolation *interpol = element->giveInterpolation();
250 IntegrationRule *iRule = element->giveDefaultIntegrationRulePtr();
251
252 if ( !interpol ) {
253 OOFEM_ERROR( "Element %d not providing interpolation", element->giveNumber() );
254 }
255
256 int size = element->giveNumberOfDofManagers();
257 fullAnswer.resize(size, size);
258 fullAnswer.zero();
259 //double pok = 0.0;
260
261 for ( GaussPoint *gp: *iRule ) {
262 double dV = element->computeVolumeAround(gp);
263 interpol->evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(element) );
264 fullAnswer.plusDyadSymmUpper(n, dV);
265 //pok += ( n.at(1) * dV ); ///@todo What is this? Completely unused.
266 //volume += dV;
267 }
268
269
270 fullAnswer.symmetrized();
271 answer.resize(size);
272 for ( int i = 1; i <= size; i++ ) {
273 double sum = 0.0;
274 for ( int j = 1; j <= size; j++ ) {
275 sum += fullAnswer.at(i, j);
276 }
277
278 answer.at(i) = sum;
279 }
280}
281
282
283#ifdef __MPI_PARALLEL_MODE
284
285void
286ZZNodalRecoveryModel :: initCommMaps()
287{
288 #ifdef __MPI_PARALLEL_MODE
289 if ( initCommMap ) {
290 EngngModel *emodel = domain->giveEngngModel();
292 communicator = new NodeCommunicator(emodel, commBuff, emodel->giveRank(),
293 emodel->giveNumberOfProcesses());
294 communicator->setUpCommunicationMaps(domain->giveEngngModel(), true, true);
295 OOFEM_LOG_INFO("ZZNodalRecoveryModel :: initCommMaps: initialized comm maps");
296 initCommMap = false;
297 }
298
299 #endif
300}
301
302void
303ZZNodalRecoveryModel :: exchangeDofManValues(FloatArray &lhs, FloatMatrix &rhs, IntArray &rn)
304{
305 parallelStruct ls( &lhs, &rhs, &rn);
306
307 // exchange data for shared nodes
308 communicator->packAllData(this, & ls, & ZZNodalRecoveryModel :: packSharedDofManData);
309 communicator->initExchange(788);
310 communicator->unpackAllData(this, & ls, & ZZNodalRecoveryModel :: unpackSharedDofManData);
311 communicator->finishExchange();
312}
313
314int
315ZZNodalRecoveryModel :: packSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm)
316{
317 int result = 1;
319 const IntArray &toSendMap = processComm.giveToSendMap();
320 int nc = s->rhs->giveNumberOfColumns();
321
322 for ( int inode : toSendMap ) {
323 // toSendMap contains all shared dofmans with remote partition
324 // one has to check, if particular shared node value is available for given region
325 int indx = s->regionNodalNumbers->at( inode );
326 if ( indx ) {
327 // pack "1" to indicate that for given shared node this is a valid contribution
328 result &= pcbuff->write(1);
329 result &= pcbuff->write( s->lhs->at(indx) );
330 for ( int j = 1; j <= nc; j++ ) {
331 result &= pcbuff->write( s->rhs->at(indx, j) );
332 }
333
334 //printf("[%d] ZZ: Sending data for shred node %d[%d]\n", domain->giveEngngModel()->giveRank(),
335 // inode, domain->giveDofManager(inode)->giveGlobalNumber());
336 } else {
337 // ok shared node is not in active region (determined by s->regionNodalNumbers)
338 result &= pcbuff->write(0);
339 }
340 }
341
342 return result;
343}
344
345int
346ZZNodalRecoveryModel :: unpackSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm)
347{
348 int result = 1;
349 int flag;
350 const IntArray &toRecvMap = processComm.giveToRecvMap();
352 double value;
353 int nc = s->rhs->giveNumberOfColumns();
354
355 for ( int inode : toRecvMap ) {
356 int indx = s->regionNodalNumbers->at( inode );
357 // toRecvMap contains all shared dofmans with remote partition
358 // one has to check, if particular shared node received contribution is available for given region
359 result &= pcbuff->read(flag);
360 if ( flag ) {
361 // "1" to indicates that for given shared node this is a valid contribution
362 result &= pcbuff->read(value);
363 // now check if we have a valid number
364 if ( indx ) {
365 s->lhs->at(indx) += value;
366 }
367
368 for ( int j = 1; j <= nc; j++ ) {
369 result &= pcbuff->read(value);
370 if ( indx ) {
371 s->rhs->at(indx, j) += value;
372 }
373 }
374
375 //if (indx) printf("[%d] ZZ: Receiving data for shred node %d[%d]\n", domain->giveEngngModel()->giveRank(),
376 // inode, domain->giveDofManager(inode)->giveGlobalNumber());
377 }
378 }
379
380 return result;
381}
382
383#endif
384} // end namespace oofem
#define REGISTER_NodalRecoveryModel(class, type)
elementParallelMode giveParallelMode() const
Definition element.h:1139
virtual int giveNumberOfDofManagers() const
Definition element.h:695
DofManager * giveDofManager(int i) const
Definition element.C:553
int giveNumberOfProcesses() const
Returns the number of collaborating processes.
Definition engngm.h:1156
int giveRank() const
Returns domain rank in a group of collaborating processes (0..groupSize-1).
Definition engngm.h:1154
virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
virtual Interface * giveInterface(InterfaceType t)
Definition femcmpnn.h:181
int giveNumber() const
Definition femcmpnn.h:104
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
*Sets size of receiver to be an empty matrix It will have zero rows and zero columns size void clear()
int giveNumberOfColumns() const
Returns number of columns of receiver.
void plusDyadUnsym(const FloatArray &a, const FloatArray &b, double dV)
void zero()
Zeroes all coefficient of receiver.
void plusDyadSymmUpper(const FloatArray &a, double dV)
double at(std::size_t i, std::size_t j) const
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
bool initCommMap
Communication init flag.
int initRegionNodeNumbering(IntArray &regionNodalNumbers, int &regionDofMans, Set &region)
int updateRegionRecoveredValues(const IntArray &regionNodalNumbers, int regionValSize, const FloatArray &rhs)
CommunicatorBuff * commBuff
Common Communicator buffer.
NodalRecoveryModel(Domain *d)
Constructor.
StateCounterType stateCounter
Time stamp of recovered values.
InternalStateType valType
Determines the type of recovered values.
ProblemCommunicator * communicator
Communicator.
int read(int *data, std::size_t count) override
Reads count integer values into array pointed by data.
Definition processcomm.h:94
int write(const int *data, std::size_t count) override
Writes count integer values from array pointed by data.
Definition processcomm.h:86
const IntArray & giveToRecvMap()
ProcessCommunicatorBuff * giveProcessCommunicatorBuff()
Returns communication buffer.
const IntArray & giveToSendMap()
const IntArray & giveElementList()
Definition set.C:158
StateCounterType giveSolutionStateCounter()
Definition timestep.h:211
virtual bool ZZNodalRecoveryMI_computeNValProduct(FloatMatrix &answer, InternalStateType type, TimeStep *tStep)
virtual void ZZNodalRecoveryMI_computeNNMatrix(FloatArray &answer, InternalStateType type)
void exchangeDofManValues(FloatArray &lhs, FloatMatrix &rhs, IntArray &rn)
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
#define OOFEM_LOG_INFO(...)
Definition logger.h:143
#define OOFEM_LOG_RELEVANT(...)
Definition logger.h:142
const char * __InternalStateTypeToString(InternalStateType _value)
Definition cltypes.C:309
@ Element_local
Element is local, there are no contributions from other domains to this element.
Definition element.h:88
@ CBT_dynamic
double sum(const FloatArray &x)
@ ZZNodalRecoveryModelInterfaceType
#define ZZNRM_ZERO_VALUE

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