OOFEM 3.0
Loading...
Searching...
No Matches
fecontactsurface.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
35
36#include "fecontactsurface.h"
37#include "contactpoint.h"
38#include "datastream.h"
39#include "contextioerr.h"
40#include "dynamicinputrecord.h"
41#include "set.h"
42#include "feinterpol2d.h"
43#include "feinterpol3d.h"
44#include "floatarrayf.h"
45#include "floatmatrixf.h"
46
47namespace oofem {
48
49
50FEContactSurface :: FEContactSurface(int n, Domain *d) : ContactSurface(n, d)
51{
52}
53
54
55
56void FEContactSurface :: initializeFrom(InputRecord &ir)
57{
58 ContactSurface :: initializeFrom(ir);
60}
61
62
63void
64FEContactSurface :: postInitialize()
65{
66 this->contactElementSet = domain->giveSet(this->contactElementSetNumber)->giveElementList();
67}
68
69
71FEContactSurface :: giveContactElement(int i)
72{
73 if(i == -1) {
74 return nullptr;
75 } else {
76 auto e = dynamic_cast<ContactElement*>( this->giveDomain()->giveElement(i));
77 if(e) {
78 return e;
79 } else {
80 OOFEM_ERROR("Element %d is not a contact element", i);
81 }
82 }
83}
84
86FEContactSurface :: giveContactElement_InSet(int i)
87{
88 auto e = dynamic_cast<ContactElement*>( this->giveDomain()->giveElement(this->contactElementSet.at(i)));
89 if(e) {
90 return e;
91 } else {
92 OOFEM_ERROR("Element is not a contact element");
93 }
94}
95
96
97 std::tuple<bool, FloatArrayF<2>, double, FloatArrayF<3>, FloatArrayF<3>, FloatArrayF<3>>
98FEContactSurface :: findContactPointInElement_3d(ContactPoint *cp, ContactElement *contactElement, TimeStep *tStep)
99{
100 // detailed search
101 return computeContactPointLocalCoordinates_3d(cp, contactElement, tStep);
102}
103
104
105
106 std::tuple<bool, FloatArrayF<1>, double, FloatArrayF<2>, FloatArrayF<2>>
107FEContactSurface :: findContactPointInElement_2d(ContactPoint *cp, ContactElement *contactElement, TimeStep *tStep)
108{
109 // detailed search
110 return computeContactPointLocalCoordinates_2d(cp, contactElement, tStep);
111}
112
113
114
115 std::tuple <bool, FloatArrayF<2>, double, FloatArrayF<3>,FloatArrayF<3>,FloatArrayF<3>>
116FEContactSurface :: computeContactPointLocalCoordinates_3d(ContactPoint *cp, ContactElement *contactElement, TimeStep *tStep)
117{
118
119
120 FEInterpolation3d *interpolation = dynamic_cast<FEInterpolation3d *>(contactElement->giveInterpolation());
121 if (interpolation == nullptr) {
122 OOFEM_ERROR("Wrong contact element");
123 }
124 //now apply the Newton-Raphson closest point projection
125 FEIElementDeformedGeometryWrapper cellgeo(contactElement, tStep);
126 FloatArray r, ro;
127 FloatArrayF<3> gapVector;
128 FloatArrayF<2> contactPointLocalCoords, dKsi, dFdXi;
129 FloatArrayF<3> t1, t2, unitNormal;
130 FloatMatrixF<2,3> dRodXi;
131 FloatMatrixF<2,2> kappa, m, G, invG;
132
133 cp->giveUpdatedCoordinates(r, tStep);
134 double error = 1.;
135 int iter = 0;
136 int maxIter = 100;
137 double tol = 1.e-12, point_tol = 1.e-6;
138 // test if inside
139 bool inside = true;
140 //lets minimize F = 0.5 * (r-ro)*(r-ro)
141 //initial guess is zero local coordinate
142 do {
143 std::tie(t1,t2) = interpolation->surfaceEvalBaseVectorsAt(0, contactPointLocalCoords, cellgeo);
144 interpolation->local2global(ro, contactPointLocalCoords, cellgeo);
145
146 dRodXi.setRow(t1, 0);
147 dRodXi.setRow(t2, 1);
148
149
150 gapVector = FloatArrayF<3>(r-ro);
151 //dFdXi = - dRodXi * (r - ro)
152 dFdXi = -dot(dRodXi, gapVector);
153 error = norm(dFdXi);
154
155 //get unit normal
156 unitNormal = cross(t1,t2);
157 // unitNormal /= norm(unitNormal); //the orientation of the unit normal is not relevant here, since we only ever use its square
158 if (error <= tol) {
159 break;
160 }
161
162 //get curvature
163 // kappa = [dro/dksidksi * normal, dro/dksideta * normal;
164 // dro/detadksi * normal, dro/detadeta * normal]
165 FloatMatrix d2Ndxi2;
166 interpolation->surfaceEvald2Ndxi2(d2Ndxi2, contactPointLocalCoords);
167
168 FloatArray dRodXidXi, dRodEtadEta, dRodXidEta;
169 for (int i = 1; i <= contactElement->giveNumberOfNodes(); ++i) {
170 dRodXidXi.add(d2Ndxi2.at(i, 1), cellgeo.giveVertexCoordinates(i));
171 dRodEtadEta.add(d2Ndxi2.at(i, 2), cellgeo.giveVertexCoordinates(i));
172 dRodXidEta.add(d2Ndxi2.at(i, 3), cellgeo.giveVertexCoordinates(i));
173 }
174 kappa = {
175 dRodXidXi.dotProduct(unitNormal), dRodXidEta.dotProduct(unitNormal),
176 dRodXidEta.dotProduct(unitNormal), dRodEtadEta.dotProduct(unitNormal)
177 };
178 //kappa *= 1./norm(unitNormal);
179 //get metric tensor
180 m= {
181 dot(t1,t1), dot(t1,t2),
182 dot(t2,t1), dot(t2,t2)
183 };
184 //construct G = m - gap*kappa
185 //G = m - dot(gapVector, unitNormal)/norm(unitNormal) * kappa;
186 G = m - dot(gapVector, unitNormal) * kappa;
187 //construct ksi increment
188 //dksi = -G^-1 * dFdXi
189 invG = inv(G);
190 dKsi = dot(invG, dFdXi);
191 //
192 contactPointLocalCoords -= dKsi;
193
194 iter++;
195 } while (iter < maxIter);
196
197 if (iter == maxIter) {
198 //OOFEM_WARNING("Closest point projection on contact surface failed to converge in %i iterations (error = %d)",iter, error);
199 inside = false;
200 }
201
202
203 for (int i = 1; i <= 2; i++) {
204 if (contactPointLocalCoords.at(i) < (-1. - point_tol)) {
205 contactPointLocalCoords.at(i) = -1.;
206 inside = false;
207 //@todo:verify
208 //inside = true;
209 }
210 else if (contactPointLocalCoords.at(i) > (1. + point_tol)) {
211 contactPointLocalCoords.at(i) = 1.;
212 inside = false;
213 //@todo:verify
214 //inside = true;
215 }
216 }
217 //
218 auto gap = dot(gapVector,unitNormal)/norm(unitNormal);
219 //
220 return std::make_tuple(inside, contactPointLocalCoords, gap, unitNormal, t1, t2);
221}
222
223
224
225
226
227
228 std::tuple <bool, FloatArrayF<1>, double, FloatArrayF<2>,FloatArrayF<2>>
229FEContactSurface :: computeContactPointLocalCoordinates_2d(ContactPoint *cp, ContactElement *contactElement, TimeStep *tStep)
230{
231
232
233 FEInterpolation2d *interpolation = dynamic_cast<FEInterpolation2d *>(contactElement->giveInterpolation());
234 if (interpolation == nullptr) {
235 OOFEM_ERROR("Wrong contact element");
236 }
237 //now apply the Newton-Raphson closest point projection
238 FEIElementDeformedGeometryWrapper cellgeo(contactElement, tStep);
239 FloatArray r, ro;
240 FloatArrayF<2> gapVector;
241 double dFdXi;
242 FloatArrayF<1> contactPointLocalCoords;
243 FloatArrayF<2> t1, normal;
244 FloatMatrixF<2,3> dRodXi;
245
246 cp->giveUpdatedCoordinates(r, tStep);
247 double error = 1.;
248 int iter = 0;
249 int maxIter = 100;;
250 double tol = 1.e-8, point_tol = 5.e-2;
251 // test if inside
252 bool inside = true;
253 //lets minimize F = 0.5 * (r-ro)*(r-ro)
254 //initial guess is zero local coordinate
255 do {
256 t1 = interpolation->surfaceEvalBaseVectorsAt(1, contactPointLocalCoords, cellgeo);
257 interpolation->local2global(ro, contactPointLocalCoords, cellgeo);
258 gapVector = FloatArrayF<2>(r-ro);
259 //dFdXi = - dRodXi * (r - ro)
260 dFdXi = -dot(t1, gapVector);
261 error = fabs(dFdXi);
262
263 //get normal. note: not normalized
264 normal = {+t1.at(2), -t1.at(1)};
265 if (error <= tol) {
266 break;
267 }
268
269 //get curvature
270 // kappa = [dro/dksidksi * normal, dro/dksideta * normal;
271 // dro/detadksi * normal, dro/detadeta * normal]
272 FloatMatrix d2Ndxi2;
273 interpolation->surfaceEvald2Ndxi2(d2Ndxi2, contactPointLocalCoords);
274
275 FloatArray dRodXidXi;
276 for (int i = 1; i <= contactElement->giveNumberOfNodes(); ++i) {
277 dRodXidXi.add(d2Ndxi2.at(i, 1), cellgeo.giveVertexCoordinates(i));
278 }
279 auto G = dot(t1,t1) - dot(gapVector, normal) * dRodXidXi.dotProduct(normal);
280 //@todo: the factor 2 here is because the element goes from -1 to 1 so the length is 2 - we have to somehow introduce it into the interpolation or change somethig as it shouldn't be there for element parametrized on the interval 0,1
281 contactPointLocalCoords.at(1) -= dFdXi/G ;
282 iter++;
283 } while (iter < maxIter);
284
285 if (iter == maxIter) {
286 //OOFEM_WARNING("Closest point projection on contact surface failed to converge in %i iterations (error = %d)",iter, error);
287 }
288
289
290 if (contactPointLocalCoords.at(1) < (-1. - point_tol)) {
291 contactPointLocalCoords.at(1) = -1.;
292 inside = false;
293 } else if (contactPointLocalCoords.at(1) > (1. + point_tol)) {
294 contactPointLocalCoords.at(1) = 1.;
295 inside = false;
296 }
297 //
298 auto gap = dot(gapVector,normal)/norm(normal);
299 //
300 return std::make_tuple(inside, contactPointLocalCoords, gap, normal, t1);
301}
302
303
304
305
306
307}
Represents a discrete contact point used in contact mechanics formulations.
virtual void giveUpdatedCoordinates(FloatArray &coords, TimeStep *tStep)=0
Returns updated coordinates of the contact point for the given time step.
ContactSurface(int n, Domain *aDomain)
Array containing dofmanager numbers.
virtual FEInterpolation * giveInterpolation() const
Definition element.h:648
virtual int giveNumberOfNodes() const
Definition element.h:703
virtual std::tuple< bool, FloatArrayF< 1 >, double, FloatArrayF< 2 >, FloatArrayF< 2 > > computeContactPointLocalCoordinates_2d(ContactPoint *cp, ContactElement *contactElement, TimeStep *tStep)
Computes 2D local (parametric) coordinate of a projected contact point on a contact element.
virtual std::tuple< bool, FloatArrayF< 2 >, double, FloatArrayF< 3 >, FloatArrayF< 3 >, FloatArrayF< 3 > > computeContactPointLocalCoordinates_3d(ContactPoint *cp, ContactElement *contactElement, TimeStep *tStep)
Computes 3D local (parametric) coordinates of a projected contact point on a contact element.
IntArray contactElementSet
Array containing dofmanager numbers.
const FloatArray giveVertexCoordinates(int i) const override
Definition feinterpol.C:65
virtual FloatArrayF< 2 > surfaceEvalBaseVectorsAt(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
virtual void surfaceEvald2Ndxi2(FloatMatrix &answer, const FloatArray &lcoords) const override
virtual std::tuple< FloatArrayF< 3 >, FloatArrayF< 3 > > surfaceEvalBaseVectorsAt(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const
void surfaceEvald2Ndxi2(FloatMatrix &answer, const FloatArray &lcoords) const override
virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
Domain * giveDomain() const
Definition femcmpnn.h:97
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
double & at(std::size_t i)
double dotProduct(const FloatArray &x) const
Definition floatarray.C:524
void add(const FloatArray &src)
Definition floatarray.C:218
void setRow(const FloatArrayF< M > &src, int r)
double at(std::size_t i, std::size_t j) const
#define OOFEM_ERROR(...)
Definition error.h:79
#define _IFT_FEContactSurface_contactElementSetNumber
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
double norm(const FloatArray &x)
FloatArrayF< 3 > cross(const FloatArrayF< 3 > &x, const FloatArrayF< 3 > &y)
Computes $ x \cross y $.
double dot(const FloatArray &x, const FloatArray &y)
FloatMatrixF< N, N > inv(const FloatMatrixF< N, N > &mat, double zeropiv=1e-24)
Computes the inverse.

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