OOFEM 3.0
Loading...
Searching...
No Matches
mmaleastsquareprojection.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 "mathfem.h"
37#include "gausspoint.h"
38#include "element.h"
39#include "domain.h"
40#include "spatiallocalizer.h"
41#include "integrationrule.h"
42#include "connectivitytable.h"
43#include "dynamicinputrecord.h"
44#include "classfactory.h"
45
46namespace oofem {
48
49MMALeastSquareProjection :: MMALeastSquareProjection() : MaterialMappingAlgorithm()
50{
51 this->stateFilter = 0;
52 this->regionFilter = 1;
53 this->patchDomain = NULL;
54}
55
56MMALeastSquareProjection :: ~MMALeastSquareProjection() { }
57
58void
59MMALeastSquareProjection :: __init(Domain *dold, IntArray &type, const FloatArray &coords, Set &elemSet, TimeStep *tStep, bool iCohesiveZoneGP)
60//(Domain* dold, IntArray& varTypes, GaussPoint* gp, TimeStep* tStep)
61{
62 GaussPoint *sourceIp;
63 Element *sourceElement;
65 IntegrationRule *iRule;
66
67 IntArray patchList;
68
69 this->patchDomain = dold;
70 // find the closest IP on old mesh
71 sourceElement = sl->giveElementContainingPoint(coords, elemSet);
72
73 if ( !sourceElement ) {
74 OOFEM_ERROR("no suitable source element found");
75 }
76
77 // determine the type of patch
78 Element_Geometry_Type egt = sourceElement->giveGeometryType();
79 if ( egt == EGT_line_1 ) {
81 } else if ( ( egt == EGT_triangle_1 ) || ( egt == EGT_quad_1 ) ) {
83 } else {
84 OOFEM_ERROR("unsupported material mode");
85 }
86
87 /* Determine the state of closest point.
88 * Only IP in the neighbourhood with same state can be used
89 * to interpolate the values.
90 */
91 FloatArray dam;
92 int state = 0;
93 if ( this->stateFilter ) {
94 iRule = sourceElement->giveDefaultIntegrationRulePtr();
95 for ( GaussPoint *gp: *iRule ) {
96 sourceElement->giveIPValue(dam, gp, IST_PrincipalDamageTensor, tStep);
97 if ( dam.computeNorm() > 1.e-3 ) {
98 state = 1; // damaged
99 }
100 }
101 }
102
103 // from source neighbours the patch will be constructed
104 Element *element;
105 IntArray neighborList;
106 patchList.resize(1);
107 patchList.at(1) = sourceElement->giveNumber();
108 int minNumberOfPoints = this->giveNumberOfUnknownPolynomialCoefficients(this->patchType);
109 int actualNumberOfPoints = sourceElement->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints();
110 int nite = 0;
111 int elemFlag;
112 // check if number of IP in patchList is sufficient
113 // some recursion control would be appropriate
114 while ( ( actualNumberOfPoints < minNumberOfPoints ) && ( nite <= 2 ) ) {
115 //if not, construct the neighborhood
116 dold->giveConnectivityTable()->giveElementNeighbourList(neighborList, patchList);
117 // count number of available points
118 patchList.clear();
119 actualNumberOfPoints = 0;
120 for ( int i = 1; i <= neighborList.giveSize(); i++ ) {
121 if ( this->stateFilter ) {
122 element = patchDomain->giveElement( neighborList.at(i) );
123 // exclude elements in different regions
124 if ( !elemSet.hasElement( element->giveNumber() ) ) {
125 continue;
126 }
127
128 iRule = element->giveDefaultIntegrationRulePtr();
129 elemFlag = 0;
130 for ( GaussPoint *gp: *iRule ) {
131 element->giveIPValue(dam, gp, IST_PrincipalDamageTensor, tStep);
132 if ( state && ( dam.computeNorm() > 1.e-3 ) ) {
133 actualNumberOfPoints++;
134 elemFlag = 1;
135 } else if ( ( state == 0 ) && ( dam.computeNorm() < 1.e-3 ) ) {
136 actualNumberOfPoints++;
137 elemFlag = 1;
138 }
139 }
140
141 if ( elemFlag ) {
142 // include this element with corresponding state in neighbor search.
143 patchList.followedBy(neighborList.at(i), 10);
144 }
145 } else { // if (! yhis->stateFilter)
146 element = patchDomain->giveElement( neighborList.at(i) );
147 // exclude elements in different regions
148 if ( !elemSet.hasElement( element->giveNumber() ) ) {
149 continue;
150 }
151
152 actualNumberOfPoints += element->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints();
153
154 patchList.followedBy(neighborList.at(i), 10);
155 }
156 } // end loop over neighbor list
157
158 nite++;
159 }
160
161 if ( nite > 2 ) {
162 // not enough points -> take closest point projection
163 patchGPList.clear();
164 sourceIp = sl->giveClosestIP(coords, elemSet);
165 patchGPList.push_front(sourceIp);
166 //fprintf(stderr, "MMALeastSquareProjection: too many neighbor search iterations\n");
167 //exit (1);
168 return;
169 }
170
171#ifdef MMALSP_ONLY_CLOSEST_POINTS
172 // select only the nval closest IP points
173 GaussPoint **gpList = ( GaussPoint ** ) malloc(sizeof( GaussPoint * ) * actualNumberOfPoints);
174 FloatArray dist(actualNumberOfPoints), srcgpcoords;
175 int npoints = 0;
176 // check allocation of gpList
177 if ( gpList == NULL ) {
178 OOFEM_FATAL("memory allocation error");
179 }
180
181 for ( int ielem = 1; ielem <= patchList.giveSize(); ielem++ ) {
182 element = patchDomain->giveElement( patchList.at(ielem) );
183 iRule = element->giveDefaultIntegrationRulePtr();
184 for ( auto &srcgp: *iRule ) {
185 if ( element->computeGlobalCoordinates( srcgpcoords, * ( srcgp->giveNaturalCoordinates() ) ) ) {
186 element->giveIPValue(dam, srcgp, IST_PrincipalDamageTensor, tStep);
187 if ( this->stateFilter ) {
188 // consider only points with same state
189 if ( ( ( state == 1 ) && ( norm(dam) > 1.e-3 ) ) || ( ( ( state == 0 ) && norm(dam) < 1.e-3 ) ) ) {
190 npoints++;
191 dist.at(npoints) = distance(coords, srcgpcoords);
192 gpList [ npoints - 1 ] = srcgp;
193 }
194 } else {
195 // take all points into account
196 npoints++;
197 dist.at(npoints) = distance(coords, srcgpcoords);
198 gpList [ npoints - 1 ] = srcgp;
199 }
200 } else {
201 OOFEM_ERROR("computeGlobalCoordinates failed");
202 }
203 }
204 }
205
206 if ( npoints != actualNumberOfPoints ) {
207 OOFEM_ERROR("internal error");
208 }
209
210 //minNumberOfPoints = min (actualNumberOfPoints, minNumberOfPoints+2);
211
212 patchGPList.clear();
213 // now find the minNumberOfPoints with smallest distance
214 // from point of interest
215 double swap, minDist;
216 int minDistIndx = 0;
217 // loop over all points
218 for ( int i = 1; i <= minNumberOfPoints; i++ ) {
219 minDist = dist.at(i);
220 minDistIndx = i;
221 // search for point with i-th smallest distance
222 for ( j = i + 1; j <= actualNumberOfPoints; j++ ) {
223 if ( dist.at(j) < minDist ) {
224 minDist = dist.at(j);
225 minDistIndx = j;
226 }
227 }
228
229 // remember this ip
230 patchGPList.push_front(gpList [ minDistIndx - 1 ]);
231 swap = dist.at(i);
232 dist.at(i) = dist.at(minDistIndx);
233 dist.at(minDistIndx) = swap;
234 srcgp = gpList [ i - 1 ];
235 gpList [ i - 1 ] = gpList [ minDistIndx - 1 ];
236 gpList [ minDistIndx - 1 ] = srcgp;
237 }
238
239 if ( patchGPList.size() != minNumberOfPoints ) {
240 OOFEM_ERROR("internal error 2");
241 exit(1);
242 }
243
244 free(gpList);
245
246#else
247
248 // take all neighbors
249 patchGPList.clear();
250 for ( int ielem = 1; ielem <= patchList.giveSize(); ielem++ ) {
251 element = patchDomain->giveElement( patchList.at(ielem) );
252 iRule = element->giveDefaultIntegrationRulePtr();
253 for ( GaussPoint *gp: *iRule ) {
254 patchGPList.push_front( gp );
255 }
256 }
257
258#endif
259}
260
261
262void
263MMALeastSquareProjection :: finish(TimeStep *tStep)
264{ }
265
266
267int
268MMALeastSquareProjection :: __mapVariable(FloatArray &answer, const FloatArray &targetCoords,
269 InternalStateType type, TimeStep *tStep)
270{
271 //int nelem, ielem,
273 int nval = 0;
274 FloatArray ipVal, coords, P;
275 FloatMatrix a, rhs, x;
276 Element *element;
277 //IntegrationRule* iRule;
278
279 a.resize(neq, neq);
280 a.zero();
281
282 // determine the value from patch
283 int size = (int) patchGPList.size();
284 if ( size == 1 ) {
285 GaussPoint *srcgp = *patchGPList.begin();
286 srcgp->giveElement()->giveIPValue(answer, srcgp, type, tStep);
287 } else if ( size < neq ) {
288 OOFEM_ERROR("internal error");
289 } else {
290 for ( auto &srcgp: patchGPList ) {
291 element = srcgp->giveElement();
292 element->giveIPValue(ipVal, srcgp, type, tStep);
293 if ( nval == 0 ) {
294 nval = ipVal.giveSize();
295 rhs.resize(neq, nval);
296 rhs.zero();
297 }
298 if ( element->computeGlobalCoordinates( coords, srcgp->giveNaturalCoordinates() ) ) {
299 coords.subtract(targetCoords);
300 // compute ip contribution
301 this->computePolynomialTerms(P, coords, patchType);
302 for ( int j = 1; j <= neq; j++ ) {
303 for ( int k = 1; k <= nval; k++ ) {
304 rhs.at(j, k) += P.at(j) * ipVal.at(k);
305 }
306
307 for ( int k = 1; k <= neq; k++ ) {
308 a.at(j, k) += P.at(j) * P.at(k);
309 }
310 }
311 } else {
312 OOFEM_ERROR("computeGlobalCoordinates failed");
313 }
314 }
315
316#if 0
317 // check for correct solution
318 FloatMatrix aa = a;
319#endif
320 a.solveForRhs(rhs, x);
321#if 0
322 // check for correct solution
323 FloatMatrix tmp;
324 tmp.beProductOf(aa, x);
325 for ( j = 1; j <= neq; j++ ) {
326 for ( k = 1; k <= nval; k++ ) {
327 if ( fabs( tmp.at(j, k) - rhs.at(j, k) ) > 1.e-3 ) {
328 printf("(SE)");
329 }
330 }
331 }
332
333#endif
334 // determine the value from patch
335 FloatArray zeroCoords(targetCoords.giveSize()); // set to zero implicitly
336 //gp->giveElement()->computeGlobalCoordinates (coords, gp->giveNaturalCoordinates());
337 this->computePolynomialTerms(P, zeroCoords, patchType);
338
339 answer.resize(nval);
340 answer.zero();
341 for ( int i = 1; i <= nval; i++ ) {
342 for ( int j = 1; j <= neq; j++ ) {
343 answer.at(i) += P.at(j) * x.at(j, i);
344 }
345 }
346 }
347
348 /*
349 * double ee;
350 * aa.subtract (answer);
351 * ee = sqrt(dotProduct(aa,aa,aa.giveSize()));
352 * if ((aa.giveSize() != answer.giveSize()) || (ee > 1.e-6)) {
353 * printf("Diference @@@@@!\n");
354 * exit (1);
355 * }
356 */
357 return 1;
358}
359
360int
361MMALeastSquareProjection :: mapStatus(MaterialStatus &oStatus) const
362{
363 OOFEM_ERROR("not implemented yet.")
364}
365
366void
367MMALeastSquareProjection :: computePolynomialTerms(FloatArray &P, const FloatArray &coords, MMALeastSquareProjectionPatchType type)
368{
369 if ( type == MMALSPPatchType_2dq ) {
370 /*
371 * P.resize (1);
372 * P.at(1) = 1.0;
373 */
374 /*
375 * P.resize (3);
376 * P.at(1) = coords.at(1);
377 * P.at(2) = coords.at(2);
378 * P.at(3) = 1.0;
379 */
380
381 P.resize(6);
382 P.at(1) = 1.0;
383 P.at(2) = coords.at(1);
384 P.at(3) = coords.at(2);
385 P.at(4) = coords.at(1) * coords.at(2);
386 P.at(5) = coords.at(1) * coords.at(1);
387 P.at(6) = coords.at(2) * coords.at(2);
388 } else if ( type == MMALSPPatchType_1dq ) {
389 P.resize(3);
390 P.at(1) = coords.at(1) * coords.at(1);
391 P.at(2) = coords.at(1);
392 P.at(3) = 1.0;
393 } else {
394 OOFEM_ERROR("unknown regionType");
395 }
396}
397
398int
399MMALeastSquareProjection :: giveNumberOfUnknownPolynomialCoefficients(MMALeastSquareProjectionPatchType regType)
400{
401 if ( regType == MMALSPPatchType_2dq ) {
402 return 6;
403 } else if ( regType == MMALSPPatchType_1dq ) {
404 return 3;
405 } else {
406 return 0;
407 }
408}
409
410
411void
412MMALeastSquareProjection :: initializeFrom(InputRecord &ir)
413{
414 this->stateFilter = 0;
416
417 this->regionFilter = 0;
419}
420
421
422void MMALeastSquareProjection :: giveInputRecord(DynamicInputRecord &input)
423{
424 if ( this->stateFilter ) {
426 }
427 if ( this->regionFilter ) {
429 }
430}
431} // end namespace oofem
#define REGISTER_MaterialMappingAlgorithm(class, type)
void giveElementNeighbourList(IntArray &answer, const IntArray &elemList)
SpatialLocalizer * giveSpatialLocalizer()
Definition domain.C:1255
ConnectivityTable * giveConnectivityTable()
Definition domain.C:1240
void setField(int item, InputFieldType id)
virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords)
Definition element.C:1225
virtual IntegrationRule * giveDefaultIntegrationRulePtr()
Definition element.h:886
virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
Definition element.C:1298
virtual Element_Geometry_Type giveGeometryType() const =0
int giveNumber() const
Definition femcmpnn.h:104
double computeNorm() const
Definition floatarray.C:861
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 zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void subtract(const FloatArray &src)
Definition floatarray.C:320
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
void zero()
Zeroes all coefficient of receiver.
double at(std::size_t i, std::size_t j) const
bool solveForRhs(const FloatArray &b, FloatArray &answer, bool transpose=false)
Element * giveElement()
Returns corresponding element to receiver.
Definition gausspoint.h:187
void followedBy(const IntArray &b, int allocChunk=0)
Definition intarray.C:94
void resize(int n)
Definition intarray.C:73
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
int giveNumberOfIntegrationPoints() const
int regionFilter
If set, then only IP in the same region are taken into account.
std ::list< GaussPoint * > patchGPList
List of Gp participating in patch.
MMALeastSquareProjectionPatchType patchType
Type of patch.
int giveNumberOfUnknownPolynomialCoefficients(MMALeastSquareProjectionPatchType regType)
int stateFilter
If set, then only IP in the neighbourhood with same state can be used to interpolate the values.
void computePolynomialTerms(FloatArray &P, const FloatArray &coords, MMALeastSquareProjectionPatchType type)
bool hasElement(int elem) const
Return True if given element is contained.
Definition set.C:245
virtual GaussPoint * giveClosestIP(const FloatArray &coords, int region, bool iCohesiveZoneGP=false)=0
virtual Element * giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList=nullptr)=0
#define OOFEM_FATAL(...)
Definition error.h:78
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define _IFT_MMALeastSquareProjection_statefilter
#define _IFT_MMALeastSquareProjection_regionfilter
double norm(const FloatArray &x)
double distance(const FloatArray &x, const FloatArray &y)

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