Plugins
Loading...
Searching...
No Matches
ls_curvature2d_impl.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015: G-CSC, Goethe University Frankfurt
3 * Author: Christian Wehner
4 *
5 * This file is part of UG4.
6 *
7 * UG4 is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License version 3 (as published by the
9 * Free Software Foundation) with the following additional attribution
10 * requirements (according to LGPL/GPL v3 §7):
11 *
12 * (1) The following notice must be displayed in the Appropriate Legal Notices
13 * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 *
15 * (2) The following notice must be displayed at a prominent place in the
16 * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 *
18 * (3) The following bibliography is recommended for citation and must be
19 * preserved in all covered files:
20 * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 * parallel geometric multigrid solver on hierarchically distributed grids.
22 * Computing and visualization in science 16, 4 (2013), 151-164"
23 * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 * flexible software system for simulating pde based models on high performance
25 * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU Lesser General Public License for more details.
31 */
32
33namespace ug{
34namespace LevelSet{
35
36int bubblesort(std::vector<number> array,std::vector<int>& list)
37{
38 int i,j,mini,k;
39 int length=array.size();
40 number min;
41 for (i=0;i<length;i++) list[i]=i;
42 for (i=0;i<length-1;i++){
43 min = array[i];
44 mini= i;
45 for (j=i+1;j<length;j++){
46 if (array[j]<min){
47 mini = j;
48 min = array[j];
49 };
50 };
51 array[mini] = array[i];
52 k=list[i];
53 list[i] = list[mini];
54 list[mini] = k;
55 array[i] = min;
56 };
57 return 0;
58};
59
60/* Next functions are self-explaining linear algebra functions
61 used below in function solveLS
62*/
63bool multMatVec(const std::vector<number>& avec, const std::vector<number>& b,std::vector<number>& c,size_t m,size_t n)
64{
65 size_t i;
66 size_t j;
67 size_t count=0;
68 for(i = 0; i < m; i = i + 1){
69 c[i]=0.0;
70 for(j = 0; j < n; j = j + 1){
71 c[i] = c[i] + avec[count] * b[j];
72 count++;
73 }
74 }
75 return true;
76}
77
78/*
79* Solve linear system for n x n - matrix given as array
80* Remark: historic document because it was computed as exercise for
81* "Algorithmische Optimierung I", WS 04/05
82*/
83bool solveLS(std::vector<number>& x,/* solution */
84 const std::vector<number>& matField,/* matrix given as field */
85 const std::vector<number>& b /* rhs */)
86{
87 size_t n=b.size();
88 number P[n][n];
89 std::vector<number> Pvec(n*n);
90 std::vector<number> b2(n);
91 number A[n][n];
92 number L[n][n];
93 number U[n][n];
94 number z[n];
95 size_t i,k,j,l;
96 bool boolean=false;
97 number d,max;
98 size_t count=0;
99 for (i=0;i<n;i++){
100 for (j=0;j<n;j++){
101 A[i][j]=matField[count];
102 if (i!=j)
103 P[i][j]=0;
104 else
105 P[i][j]=1;
106 L[i][j]=0;
107 U[i][j]=0;
108 count ++;
109 }
110 }
111 for (i=0;i<n;i++){
112 j=i;
113 // Suche groesstes Element in Spalten
114 max=std::abs(A[i][i]);
115 for (k=i+1;k<n;k++){
116 if (std::abs(A[k][i])>max){
117 j=k;
118 max=std::abs(A[k][i]);
119 };
120 };
121 //debug
122 //UG_LOG(max << "\n");
123 if (max<1e-14){
124 // A nicht invertierbar
125 // printf(".\n");
126 return false;
127 };
128 if (i!=j){
129 // Vertauschen der Zeilen
130 if (boolean==false){
131 // beim ersten Durchlauf Vertauschen der Spalten der
132 // Permutationsmatrix und der Zeilen von A,L.
133 boolean=true;
134 for (k=0;k<n;k++){
135 d=P[k][i];
136 P[k][i]=P[k][j];
137 P[k][j]=d;
138 d=A[i][k];
139 A[i][k]=A[j][k];
140 A[j][k]=d;
141 d=L[i][k];
142 L[i][k]=L[j][k];
143 L[j][k]=d;
144 };
145 } else{
146 for (k=0;k<n;k++){
147 // Vertauschen der Zeilen von P,A,L
148 d=P[i][k];
149 P[i][k]=P[j][k];
150 P[j][k]=d;
151 d=A[i][k];
152 A[i][k]=A[j][k];
153 A[j][k]=d;
154 d=L[i][k];
155 L[i][k]=L[j][k];
156 L[j][k]=d;
157 };
158 };
159 };
160 // Elimination
161 L[i][i]=1;
162 for (k=i+1;k<n;k++){
163 L[k][i]=A[k][i]/A[i][i];
164 for (l=i+1;l<n;l++){
165 A[k][l]=A[k][l]-L[k][i]*A[i][l];
166 };
167 };
168 };
169 // U ist der obere Dreiecksteil von A
170 for (i=0;i<n;i++){
171 for (j=i;j<n;j++){
172 U[i][j]=A[i][j];
173 };
174 };
175 // A*x = b <-> P*A*x = P*b
176 count = 0;
177 for (i=0;i<n;i++){
178 for (j=0;j<n;j++){
179 Pvec[count]=P[i][j];
180 count++;
181 }
182 }
183 multMatVec(Pvec,b,b2,n,n);
184 // Loese zuerst L*z = P*b
185 for (i=0;i<n;i++){
186 number s=b2[i];
187 for (j=0;j<i;j++){
188 s=s-z[j]*L[i][j];
189 };
190 z[i]=s;
191 };
192 // Loese U*x = z
193 i = n;
194 do {
195 i--;
196 number s=z[i];
197 for (j=n-1;j>i;j--){
198 s=s-x[j]*U[i][j];
199 };
200 x[i]=s/U[i][i];
201 } while (i != 0);
202 return true;
203};
204
205
206template<size_t n>
208{
209 std::vector<number> xvec(n);
210 std::vector<number> bvec(n);
211 std::vector<number> Mvec(n*n);
212 for (size_t i=0;i<n;i++){
213 bvec[i]=b[i];
214 for (size_t j=0;j<n;j++){
215 Mvec[n*i+j] = M[i][j];
216 };
217 }
218 if (solveLS(xvec,Mvec,bvec)==false) return false;
219 for (size_t i=0;i<n;i++) x[i] = xvec[i];
220 return true;
221}
222
223template<size_t m,size_t n>
225{
226 if(m<n){
227 UG_THROW("Least squares method not suitable for m x n matrix with m<n.\n");
228 }
230 MathVector<n> b2;
231 MatMultiplyMTM(M2,M);
232 TransposedMatVecMult(b2,M,b);
233 return solveLS(x,M2,b2);
234}
235
236bool leastSquares(std::vector<number>& x,const std::vector<number>& mField,const std::vector<number>& b)
237{
238 size_t m = b.size();
239 size_t n = x.size();
240 if (mField.size()!=m*n){
241 n = mField.size()/b.size();
242 }
243 std::vector<number> tmmField(n*n);
244 std::vector<number> tmb(n);
245 number z;
246 // compute A^t * A
247 for (size_t i=0;i<n;i++){
248 for (size_t j=i;j<n;j++){
249 z=0;
250 for (size_t k=0;k<m;k++){
251 z+=mField[n*k+i]*mField[n*k+j];
252 }
253 tmmField[j*n+i]=z;
254 if (j!=i) tmmField[i*n+j]=z;
255 }
256 tmb[i]=0;
257 for (size_t k=0;k<m;k++) tmb[i]+= mField[n*k+i]*b[k];
258 }
259 return solveLS(x,tmmField,tmb);
260}
261
262
263// averages positions by arithmetic mean
264/*
265 * Arithmetic Mean of Positions
266 * returns the arithmetic mean of positions
267 *
268 * \param[in] vCornerCoords positions
269 * \param[in] num number of positions
270 * \param[out] vOut arithmetic mean of positions
271
272template <typename TPosition>
273void FV1LevelSetDisc<TGridFunction>::AverageCoord(TPosition& vOut, const TPosition* vCornerCoords, size_t num)
274{
275 vOut = vCornerCoords[0];
276 for(size_t j = 1; j < num; ++j)
277 {
278 vOut += vCornerCoords[j];
279 }
280 vOut *= 1./(number)num;
281} */
282
284
292template <typename TPosition>
293void AverageCoords(TPosition& vOut, const std::vector<TPosition>& vCornerCoords, size_t num)
294{
295 vOut = vCornerCoords[0];
296 for(size_t j = 1; j < num; ++j)
297 {
298 vOut += vCornerCoords[j];
299 }
300 vOut *= 1./(number)num;
301}
302
303// computation of curvature
304template<typename TGridFunction>
305bool LevelSetCurvature<TGridFunction>::computeElementCurvature2d(number& kappa,size_t elementnoc,const std::vector<MathVector<dim> >& co,std::vector<number> phi,size_t order)
306{
307 std::vector<MathVector<dim> > interPoints;
308 size_t nOfPoints=co.size();
309 interPoints.resize(elementnoc);
310 std::vector<number> distToBaseP(nOfPoints);
311 std::vector<int> sortedList(nOfPoints);
312 MathVector<dim> elemBasePoint;
313 size_t interpointssize = 0;
314 // compute element base point
315 for (size_t i=0;i<elementnoc;i++){
316 if (phi[i]==0){
317 interPoints[interpointssize]=co[i];
318 interpointssize++;
319 continue;
320 };
321 for (size_t j=i+1;j<elementnoc;j++){
322 if (phi[i]*phi[j]<0){
323 interPoints[interpointssize]=co[i];
324 interpointssize++;
325 }
326 }
327 }
328 AverageCoords(elemBasePoint,interPoints,interpointssize);
329 //debugUG_LOG("base point: " << elemBasePoint << "\n");
330 for (size_t i=0;i<nOfPoints;i++){
331 distToBaseP[i]=VecDistance(co[i],elemBasePoint);
332 //debugUG_LOG("dTBp[" << i << "]=" << distToBaseP[i] << "\n");
333 };
334 // sort nodes by distance to base point
335 distToBaseP.resize(nOfPoints);
336 sortedList.resize(nOfPoints);
337 bubblesort(distToBaseP,sortedList);
338 size_t criticalnofinterp;
339 if (order==2) criticalnofinterp=5;
340 if (order==3) criticalnofinterp=7;
341 size_t nrOfInterPoints=0;
342 std::vector<number> mat;
343 size_t vlength=(size_t)round(0.5*(order+1)*(order+2));
344 mat.resize(vlength*vlength);
345 std::vector<number> interphi;
346 std::vector<number> coeffs;
347 interphi.resize(vlength);
348 coeffs.resize(vlength);
349 for (size_t i=criticalnofinterp*(vlength-1);i<vlength*vlength;i++){
350 mat[i] = (number)(0.8*i*i-0.4*i)/(i+1)+i*i-0.5+sin(0.3*i)+cos(0.75*i)+i*i*i-exp(0.1*i);
351 };
352 size_t matindex=0;
353 //debugUG_LOG("####### nofpoints=" << nOfPoints << "\n");
354 for (size_t j=0;j<nOfPoints;j++){
355 size_t i=sortedList[j];
356 //debugUG_LOG("list[" << j << "]=" << sortedList[j] << "\n");
357 for (size_t ii=0;ii<=order;ii++){
358 for (size_t k=0;k<=ii;k++){
359 //debugUG_LOG(i << " " << co[i] << "\n");
360 mat[matindex]=std::pow((number)co[i][0],(int)(ii-k))*std::pow((number)co[i][1],(int)k);
361 matindex++;
362 };
363 };
364 interphi[nrOfInterPoints]=phi[i];
365 //debugUG_LOG("rhs[" << nrOfInterPoints << "] = " << interphi[nrOfInterPoints] << "\n");
366 //debugfor (size_t kdebug=0;kdebug<nrOfInterPoints*vlength;kdebug++){
367 //debugUG_LOG(mat[kdebug] << "\n");
368 //debug}
369 //debugUG_LOG("------------------------------------------- " << j << "\n");
370 if (j>=criticalnofinterp){
371 //debugUG_LOG("********************\n");
372 if (solveLS(coeffs,mat,interphi)==false){
373 matindex-=vlength;
374 continue;
375 };
376 };
377 //debugUG_LOG("co(" << nrOfInterPoints+1 << ",:)=[" << co[i][0] << "," << co[i][1] << "];" << " phi(" << nrOfInterPoints+1 << ")=" << phi[i] << ";\n");
378 nrOfInterPoints++;
379 if (nrOfInterPoints==vlength) break;
380 };
381 if (nrOfInterPoints<vlength){
382 UG_LOG("warning: not enough interpolations points for desired order "<< order << " (found " << nrOfInterPoints << ", needed " << vlength << ") Reduce order.\n");
383 if (order==1) return false;
384 if (computeElementCurvature2d(kappa,elementnoc,co,phi,order-1)==true) return true; else return false;
385 }
386 number dxphi,dyphi,dxxphi,dxyphi,dyyphi;
387 //debugUG_LOG("coeff.size =" << coeffs.size() << "\n");
388 //debugfor (size_t j=0;j<coeffs.size();j++){
389 //debugUG_LOG("coeff[" << j << "]=" << coeffs[j] << "\n");
390 //debug}
391 if (order==2){
392 dxphi=coeffs[1]+2*coeffs[3]*elemBasePoint[0]+coeffs[4]*elemBasePoint[1];
393 dyphi=coeffs[2]+coeffs[4]*elemBasePoint[0]+2*coeffs[5]*elemBasePoint[1];
394 }
395 else if (order==3){
396 dxphi=coeffs[1]+2*coeffs[3]*elemBasePoint[0]+coeffs[4]*elemBasePoint[1]+3*coeffs[6]*elemBasePoint[0]*elemBasePoint[0]+2*coeffs[7]*elemBasePoint[0]*elemBasePoint[1]+coeffs[8]*elemBasePoint[1]*elemBasePoint[1];
397 dyphi=coeffs[2]+coeffs[4]*elemBasePoint[0]+2*coeffs[5]*elemBasePoint[1]+coeffs[7]*elemBasePoint[0]*elemBasePoint[0]+2*coeffs[8]*elemBasePoint[0]*elemBasePoint[1]+3*coeffs[9]*elemBasePoint[1]*elemBasePoint[1];
398 } else {
399 UG_THROW("Case unsupported");
400 }
401 number gradnorm=sqrt(dxphi*dxphi+dyphi*dyphi);
402 // characteristic element length
403 number hh= std::min(VecDistance(co[0],co[1]),VecDistance(co[0],co[2]));
404 number coelemBasePoint[dim];
405 number sol[dim];
406 coelemBasePoint[0] = elemBasePoint[0] + 0.5*hh*dxphi/gradnorm;
407 coelemBasePoint[1] = elemBasePoint[1] + 0.5*hh*dyphi/gradnorm;
408 /* find intersection of line between elemBasePoint and coelemBaseP with zero level set */
409 number itgamma = 0;
410 number phival,phigamma;
411 size_t nrofiterations=0;
412 for (;nrofiterations<50;nrofiterations++){
413 number b = coelemBasePoint[0]-elemBasePoint[0];
414 number d = coelemBasePoint[1]-elemBasePoint[1];
415 sol[0] = elemBasePoint[0]+itgamma*(coelemBasePoint[0]-elemBasePoint[0]);
416 sol[1] = elemBasePoint[1]+itgamma*(coelemBasePoint[1]-elemBasePoint[1]);
417 if (order==2)
418 phival = coeffs[0]+coeffs[1]*sol[0]+coeffs[2]*sol[1]+coeffs[3]*sol[0]*sol[0]+coeffs[4]*sol[0]*sol[1]+coeffs[5]*sol[1]*sol[1];
419 if (order==3)
420 phival = coeffs[0]+coeffs[1]*sol[0]+coeffs[2]*sol[1]+coeffs[3]*sol[0]*sol[0]+coeffs[4]*sol[0]*sol[1]+coeffs[5]*sol[1]*sol[1]
421 +coeffs[6]*sol[0]*sol[0]*sol[0]+coeffs[7]*sol[0]*sol[0]*sol[1]+coeffs[8]*sol[0]*sol[1]*sol[1]+coeffs[9]*sol[1]*sol[1]*sol[1];
422 if (std::abs(phival)<1e-12) break;
423 phigamma = coeffs[1]*b+coeffs[2]*d+2*coeffs[3]*sol[0]*b+coeffs[4]*b*sol[1]+coeffs[4]*sol[0]*d+2*coeffs[5]*sol[1]*d+3*coeffs[6]*sol[0]*sol[0]*b
424 +2*coeffs[7]*sol[0]*sol[1]*b+coeffs[7]*sol[0]*sol[0]*d+coeffs[8]*b*sol[1]*sol[1]+2*coeffs[8]*sol[0]*sol[1]*d+3*coeffs[9]*sol[1]*sol[1]*d;
425 itgamma -= phival/phigamma;
426 };
427 if (nrofiterations==80){
428 UG_THROW("Diverging Newton method in curvature computation (error=" << phival << ")\n");
429 return false;
430 };
431 if (order==2){
432 dxphi=coeffs[1]+2*coeffs[3]*sol[0]+coeffs[4]*sol[1];
433 dyphi=coeffs[2]+coeffs[4]*sol[0]+2*coeffs[5]*sol[1];
434 dxxphi=2*coeffs[3];
435 dxyphi=coeffs[4];
436 dyyphi=2*coeffs[5];
437 };
438 if (order==3){
439 dxphi=coeffs[1]+2*coeffs[3]*sol[0]+coeffs[4]*sol[1]+3*coeffs[6]*sol[0]*sol[0]+2*coeffs[7]*sol[0]*sol[1]+coeffs[8]*sol[1]*sol[1];
440 dyphi=coeffs[2]+coeffs[4]*sol[0]+2*coeffs[5]*sol[1]+coeffs[7]*sol[0]*sol[0]+2*coeffs[8]*sol[0]*sol[1]+3*coeffs[9]*sol[1]*sol[1];
441 dxxphi=2*coeffs[3]+6*coeffs[6]*sol[0]+2*coeffs[7]*sol[1];
442 dxyphi=coeffs[4]+2*coeffs[7]*sol[0]+2*coeffs[8]*sol[1];
443 dyyphi=2*coeffs[5]+2*coeffs[8]*sol[0]+6*coeffs[9]*sol[1];
444 };
445 number t = sqrt(dxphi*dxphi+dyphi*dyphi);
446 kappa = - (dyyphi * dxphi * dxphi - 2 * dxyphi * dxphi * dyphi + dxxphi * dyphi * dyphi) / (t * t * t);
447// UG_LOG("kappa=" << kappa << "\n");
448// kappa = -3.333333333333333333333333333333333333333;// for debug
449// kappa = -5;// for debug
450 //debugUG_THROW("Grid Level Type not in ['top' | 'surf'].");
451 return true;
452}
453
454// computation of curvature
455template<typename TGridFunction>
456bool LevelSetCurvature<TGridFunction>::computeElementCurvature2d2(number& kappa,size_t elementnoc,const std::vector<MathVector<dim> >& co,std::vector<number> phi,size_t order,number nodefactor)
457{
458 if (order<2) return false;
459 std::vector<MathVector<dim> > interPoints;
460 size_t nOfPoints=co.size();
461 interPoints.resize(elementnoc);
462 std::vector<number> distToBaseP(nOfPoints);
463 std::vector<int> sortedList(nOfPoints);
464 MathVector<dim> elemBasePoint;
465 size_t interpointssize = 0;
466 // compute element base point
467 for (size_t i=0;i<elementnoc;i++){
468 if (phi[i]==0){
469 interPoints[interpointssize]=co[i];
470 interpointssize++;
471 continue;
472 };
473 for (size_t j=i+1;j<elementnoc;j++){
474 if (phi[i]*phi[j]<0){
475 interPoints[interpointssize]=co[i];
476 interpointssize++;
477 }
478 }
479 }
480 AverageCoords(elemBasePoint,interPoints,interpointssize);
481 //debugUG_LOG("base point: " << elemBasePoint << "\n");
482 for (size_t i=0;i<nOfPoints;i++){
483 distToBaseP[i]=VecDistance(co[i],elemBasePoint);
484 //debugUG_LOG("dTBp[" << i << "]=" << distToBaseP[i] << "\n");
485 };
486 // sort nodes by distance to base point
487 distToBaseP.resize(nOfPoints);
488 sortedList.resize(nOfPoints);
489 bubblesort(distToBaseP,sortedList);
490// for (size_t i=0;i<nOfPoints;i++) sortedList[i]=i;
491 size_t vlength=(size_t)round(0.5*(order+1)*(order+2));
492 size_t nrOfInterPoints = round(vlength*nodefactor);
493 size_t totalNrOfInterpoints = co.size();
494 if (totalNrOfInterpoints<nrOfInterPoints){
495 UG_LOG("Warning: not enough nodes for desired order " << order << " and least squares factor " << nodefactor << ". Needed " << nrOfInterPoints << " nodes, given " << totalNrOfInterpoints << " nodes. Reduce order to " << order-1 << ".\n");
496 return computeElementCurvature2d2(kappa,elementnoc,co,phi,order-1,nodefactor);
497 };
498 std::vector<number> interM(vlength*nrOfInterPoints);
499 std::vector<number> coeffs(vlength);
500 std::vector<number> interRhs(nrOfInterPoints);
501 size_t matindex = 0;
502 for (size_t j=0;j<nrOfInterPoints;j++){
503 size_t i=sortedList[j];
504 // interpolation rhs
505 interRhs[j] = phi[i];
506 // interpolation matrix
507 for (size_t ii=0;ii<=order;ii++){
508 for (size_t k=0;k<=ii;k++){
509 interM[matindex]=std::pow((number)co[i][0],(int)(ii-k))*std::pow((number)co[i][1],(int)k);
510 matindex++;
511 };
512 };
513 };
514 if (leastSquares(coeffs,interM,interRhs)==false){
515 UG_LOG("Least squares problem had no regular solution. Reduce order to " << order-1 << ".\n");
516/* for (size_t i=0;i<interM.size();i++){
517 UG_LOG(interM[i] << " ");
518 }
519 UG_LOG("-----------\n");
520 for (size_t i=0;i<nrOfInterPoints;i++){
521 UG_LOG(interRhs[i] << " ");
522 }
523 UG_LOG("\n");*/
524 return computeElementCurvature2d2(kappa,elementnoc,co,phi,order-1,nodefactor);
525 };
526 number dxphi,dyphi,dxxphi,dxyphi,dyyphi;
527 if (order==2){
528 dxphi=coeffs[1]+2*coeffs[3]*elemBasePoint[0]+coeffs[4]*elemBasePoint[1];
529 dyphi=coeffs[2]+coeffs[4]*elemBasePoint[0]+2*coeffs[5]*elemBasePoint[1];
530 };
531 if (order==3){
532 dxphi=coeffs[1]+2*coeffs[3]*elemBasePoint[0]+coeffs[4]*elemBasePoint[1]+3*coeffs[6]*elemBasePoint[0]*elemBasePoint[0]+2*coeffs[7]*elemBasePoint[0]*elemBasePoint[1]+coeffs[8]*elemBasePoint[1]*elemBasePoint[1];
533 dyphi=coeffs[2]+coeffs[4]*elemBasePoint[0]+2*coeffs[5]*elemBasePoint[1]+coeffs[7]*elemBasePoint[0]*elemBasePoint[0]+2*coeffs[8]*elemBasePoint[0]*elemBasePoint[1]+3*coeffs[9]*elemBasePoint[1]*elemBasePoint[1];
534 };
535 number gradnorm=sqrt(dxphi*dxphi+dyphi*dyphi);
536 // characteristic element length
537 number hh= min(VecDistance(co[0],co[1]),VecDistance(co[0],co[2]));
538 number coelemBasePoint[dim];
539 number sol[dim];
540 coelemBasePoint[0] = elemBasePoint[0] + 0.5*hh*dxphi/gradnorm;
541 coelemBasePoint[1] = elemBasePoint[1] + 0.5*hh*dyphi/gradnorm;
542 /* find intersection of line between elemBasePoint and coelemBaseP with zero level set */
543 number itgamma = 0;
544 number phival,phigamma;
545 size_t nrofiterations=0;
546 for (;nrofiterations<50;nrofiterations++){
547 number b = coelemBasePoint[0]-elemBasePoint[0];
548 number d = coelemBasePoint[1]-elemBasePoint[1];
549 sol[0] = elemBasePoint[0]+itgamma*(coelemBasePoint[0]-elemBasePoint[0]);
550 sol[1] = elemBasePoint[1]+itgamma*(coelemBasePoint[1]-elemBasePoint[1]);
551 if (order==2)
552 phival = coeffs[0]+coeffs[1]*sol[0]+coeffs[2]*sol[1]+coeffs[3]*sol[0]*sol[0]+coeffs[4]*sol[0]*sol[1]+coeffs[5]*sol[1]*sol[1];
553 if (order==3)
554 phival = coeffs[0]+coeffs[1]*sol[0]+coeffs[2]*sol[1]+coeffs[3]*sol[0]*sol[0]+coeffs[4]*sol[0]*sol[1]+coeffs[5]*sol[1]*sol[1]
555 +coeffs[6]*sol[0]*sol[0]*sol[0]+coeffs[7]*sol[0]*sol[0]*sol[1]+coeffs[8]*sol[0]*sol[1]*sol[1]+coeffs[9]*sol[1]*sol[1]*sol[1];
556 if (std::abs(phival)<1e-12) break;
557 phigamma = coeffs[1]*b+coeffs[2]*d+2*coeffs[3]*sol[0]*b+coeffs[4]*b*sol[1]+coeffs[4]*sol[0]*d+2*coeffs[5]*sol[1]*d+3*coeffs[6]*sol[0]*sol[0]*b
558 +2*coeffs[7]*sol[0]*sol[1]*b+coeffs[7]*sol[0]*sol[0]*d+coeffs[8]*b*sol[1]*sol[1]+2*coeffs[8]*sol[0]*sol[1]*d+3*coeffs[9]*sol[1]*sol[1]*d;
559 itgamma -= phival/phigamma;
560 };
561 if (nrofiterations==80){
562 UG_THROW("Diverging Newton method in curvature computation (error=" << phival << ")\n");
563 return false;
564 };
565 if (order==2){
566 dxphi=coeffs[1]+2*coeffs[3]*sol[0]+coeffs[4]*sol[1];
567 dyphi=coeffs[2]+coeffs[4]*sol[0]+2*coeffs[5]*sol[1];
568 dxxphi=2*coeffs[3];
569 dxyphi=coeffs[4];
570 dyyphi=2*coeffs[5];
571 };
572 if (order==3){
573 dxphi=coeffs[1]+2*coeffs[3]*sol[0]+coeffs[4]*sol[1]+3*coeffs[6]*sol[0]*sol[0]+2*coeffs[7]*sol[0]*sol[1]+coeffs[8]*sol[1]*sol[1];
574 dyphi=coeffs[2]+coeffs[4]*sol[0]+2*coeffs[5]*sol[1]+coeffs[7]*sol[0]*sol[0]+2*coeffs[8]*sol[0]*sol[1]+3*coeffs[9]*sol[1]*sol[1];
575 dxxphi=2*coeffs[3]+6*coeffs[6]*sol[0]+2*coeffs[7]*sol[1];
576 dxyphi=coeffs[4]+2*coeffs[7]*sol[0]+2*coeffs[8]*sol[1];
577 dyyphi=2*coeffs[5]+2*coeffs[8]*sol[0]+6*coeffs[9]*sol[1];
578 };
579 number t = sqrt(dxphi*dxphi+dyphi*dyphi);
580 kappa = - (dyyphi * dxphi * dxphi - 2 * dxyphi * dxphi * dyphi + dxxphi * dyphi * dyphi) / (t * t * t);
581 return true;
582}
583
584template<typename TGridFunction>
585bool LevelSetCurvature<TGridFunction>::computeElementCurvatureOnGrid2d(TGridFunction& u,size_t order,number leastSquaresFactor)
586{
587 typedef typename TGridFunction::domain_type domain_type;
588 // get grid
589 typename domain_type::grid_type& grid = *u.domain()->grid();
590 typedef typename TGridFunction::template dim_traits<dim>::const_iterator ElemIterator;
591 typedef typename TGridFunction::template dim_traits<dim>::grid_base_object ElemType;
592 typedef typename domain_type::position_accessor_type position_accessor_type;
593 const position_accessor_type& aaPos = u.domain()->position_accessor();
594 std::vector<DoFIndex> ind;
595 number maxnormerr = 0;
596 // loop elements of dimension
597 for (int si=0;si<u.num_subsets();++si){
598 ElemIterator iter = u.template begin<ElemType>(si);
599 ElemIterator iterEnd = u.template end<ElemType>(si);
600 if (u.num_fct(si)<2){
601 UG_THROW("No curvature component in approximation space.");
602 }
603 if (u.local_finite_element_id(0) != LFEID(LFEID::LAGRANGE, dim, 1)){
604 UG_THROW("First component in approximation space must be of Lagrange 1 type.");
605 }
606 if (u.local_finite_element_id(1) != LFEID(LFEID::PIECEWISE_CONSTANT,dim,0)){
607 UG_THROW("Second component in approximation space must be of piecewise constant type.");
608 }
609 std::vector<MathVector<dim> > coord;
610 std::vector<number> phi;
611 std::vector<Vertex*> nbrs;
612 std::vector<Vertex*> nbrCandidates;
613 size_t depth=order;
614 std::vector<size_t> stageStart(depth+2);
615 for( ;iter !=iterEnd; ++iter)
616 {
617 // get Elem
618 ElemType* elem = *iter;
619 // get position accessor
620 size_t noc=elem->num_vertices();
621 nbrs.resize(noc);
622 phi.resize(noc);
623 // check if zero level set is on element
624 bool onls=false;
625 bool nonzerophifound=false;
626 number nonzerophi;
627 //debug UG_LOG("noc = " << noc << "\n");
628 for (size_t i=0;i<noc;i++){
629 nbrs[i]=elem->vertex(i);
630 u.inner_dof_indices(nbrs[i], 0, ind);
631 phi[i] = DoFRef(u, ind[0]);
632 if (nonzerophifound==false){
633 if (phi[i]!=0){
634 nonzerophifound=true;
635 nonzerophi=phi[i];
636 }
637 } else {
638 if (nonzerophi*phi[i]<0){
639 onls=true;
640 }
641 }
642 };
643 if (onls==false) continue;
644 // collect neighbor nodes for higher order interpolation
645 stageStart[0]=0;
646 for (size_t i=1;i<depth+2;i++){
647 stageStart[i]=noc;
648 }
649 //debugUG_LOG("------------------------------------------\n");
650 for (size_t stage=0;stage<depth;stage++){
651 //debugUG_LOG("stage= " << stage << "\n");
652 for (size_t i=stageStart[stage];i<stageStart[stage+1];i++){
653 //debugUG_LOG("i =" << i << " stageStart[stage+1]=" << stageStart[stage+1] << "\n");
654 CollectNeighbors(nbrCandidates, grid, nbrs[i]);
655 for (size_t j=0;j<nbrCandidates.size();j++){
656 bool newNeighbor=true;
657 for (size_t k=0;k<nbrs.size();k++){
658 if (nbrCandidates[j]==nbrs[k]){
659 newNeighbor=false;
660 break;
661 }
662 };
663 if (newNeighbor==true){
664 nbrs.push_back(nbrCandidates[j]);
665 //debugUG_LOG("new size : " << nbrs.size() << "\n");
666 //debugUG_LOG(nbrs.size()-1 << " " << aaPos[nbrs[nbrs.size()-1]] << "\n");
667 };
668 };
669 };
670 stageStart[stage+2]=nbrs.size();
671 //debugUG_LOG(" # stageStart[" << stage+2 << "]=" << stageStart[stage+2] << "\n");
672 };
673 phi.resize(nbrs.size());
674 coord.resize(nbrs.size());
675 // UG_LOG("nbrs.size=" << nbrs.size() << "\n");
676 //debugUG_LOG("### " << aaPos[nbrs[0]] << "\n");
677 for (size_t i=0;i<nbrs.size();i++){
678 //debug UG_LOG(i << "\n");
679// UG_LOG("--- " << aaPos[nbrs[i]] << "\n");
680 coord[i] = aaPos[nbrs[i]];
681 //debugUG_LOG("co0(" << i+1 << ",:)=[" << coord[i][0] << "," << coord[i][1] << "];\n");
682 if (i<noc) continue;
683 u.inner_dof_indices(nbrs[i], 0, ind);
684 phi[i] = DoFRef(u, ind[0]);
685 //debug
686// UG_LOG("phi[i]=" << phi[i] << "\n");
687 };
688 number kappa;
689 computeElementCurvature2d(kappa,noc,coord,phi,order);
690// computeElementCurvature2d2(kappa,noc,coord,phi,order,leastSquaresFactor);
691 u.dof_indices(elem,1,ind);
692 DoFRef(u,ind[0]) = kappa;
693 if (m_exactcurvatureknown==true)
694 if (std::abs(kappa+m_exactcurv)>maxnormerr){
695 maxnormerr =std::abs(kappa+m_exactcurv);
696 }
697 //u.inner_dof_indices(elem, 1, ind);
698 //DoFRef(u,ind[1]) = kappa;
699 };
700 };
701 if (m_exactcurvatureknown==true) UG_LOG("curvature maximum error " << maxnormerr << "\n");
702 return true;
703};
704
705template<typename TGridFunction>
706bool LevelSetCurvature<TGridFunction>::computeElementCurvatureFromSides(TGridFunction& u,size_t order,number leastSquaresFactor)
707{
708 typedef typename TGridFunction::domain_type domain_type;
709 typedef typename domain_type::grid_type grid_type;
710 // get grid
711 typename domain_type::grid_type& grid = *u.domain()->grid();
712 typedef typename TGridFunction::template dim_traits<dim>::grid_base_object elem_type;
713 typedef typename TGridFunction::template dim_traits<dim>::const_iterator elem_iterator;
714 typedef typename elem_type::side side_type;
715 typedef typename TGridFunction::template traits<side_type>::const_iterator side_iterator;
716 typedef typename domain_type::position_accessor_type position_accessor_type;
717 const position_accessor_type& aaPos = u.domain()->position_accessor();
718 std::vector<MultiIndex<2> > ind;
719 typedef typename Grid::AttachmentAccessor<side_type,ANumber > aSideNumber;
720 aSideNumber acEdgeCurvature;
721 ANumber aEdgeCurvature;
722 grid.template attach_to<side_type>(aEdgeCurvature);
723 acEdgeCurvature.access(grid,aEdgeCurvature);
724 static number undefined = 1953853528.340591483532;
725 SetAttachmentValues(acEdgeCurvature, grid.template begin<side_type>(), grid.template end<side_type>(), undefined);
726 number maxnormerr = 0;
727 // loop elements of dimension
728 for (int si=0;si<u.num_subsets();++si){
729 side_iterator iter = u.template begin<side_type>(si);
730 side_iterator iterEnd = u.template end<side_type>(si);
731 if (u.num_fct(si)<2){
732 UG_THROW("No curvature component in approximation space.");
733 }
734 if (u.local_finite_element_id(0) != LFEID(LFEID::LAGRANGE, dim, 1)){
735 UG_THROW("First component in approximation space must be of Lagrange 1 type.");
736 }
737 if (u.local_finite_element_id(1) != LFEID(LFEID::PIECEWISE_CONSTANT,dim,0)){
738 UG_THROW("Second component in approximation space must be of piecewise constant type.");
739 }
740 std::vector<MathVector<dim> > coord;
741 std::vector<number> phi;
742 std::vector<Vertex*> nbrs;
743 std::vector<Vertex*> nbrCandidates;
744 size_t depth=order;
745 std::vector<size_t> stageStart(depth+2);
746 for( ;iter !=iterEnd; ++iter)
747 {
748 // get Elem
749 side_type* elem = *iter;
750 // get position accessor
751 size_t noc=elem->num_vertices();
752 nbrs.resize(noc);
753 phi.resize(noc);
754 // check if zero level set is on element
755 bool onls=false;
756 bool nonzerophifound=false;
757 number nonzerophi;
758 for (size_t i=0;i<noc;i++){
759 nbrs[i]=elem->vertex(i);
760 u.inner_dof_indices(nbrs[i], 0, ind);
761 phi[i] = DoFRef(u, ind[0]);
762 if (nonzerophifound==false){
763 if (phi[i]!=0){
764 nonzerophifound=true;
765 nonzerophi=phi[i];
766 }
767 } else {
768 if (nonzerophi*phi[i]<0){
769 onls=true;
770 }
771 }
772 };
773 if (onls==false) continue;
774 // collect neighbor nodes for higher order interpolation
775 stageStart[0]=0;
776 for (size_t i=1;i<depth+2;i++){
777 stageStart[i]=noc;
778 }
779 for (size_t stage=0;stage<depth;stage++){
780 for (size_t i=stageStart[stage];i<stageStart[stage+1];i++){
781 CollectNeighbors(nbrCandidates, grid, nbrs[i]);
782 for (size_t j=0;j<nbrCandidates.size();j++){
783 bool newNeighbor=true;
784 for (size_t k=0;k<nbrs.size();k++){
785 if (nbrCandidates[j]==nbrs[k]){
786 newNeighbor=false;
787 break;
788 }
789 };
790 if (newNeighbor==true){
791 nbrs.push_back(nbrCandidates[j]);
792 };
793 };
794 };
795 stageStart[stage+2]=nbrs.size();
796 };
797 phi.resize(nbrs.size());
798 coord.resize(nbrs.size());
799 for (size_t i=0;i<nbrs.size();i++){
800 coord[i] = aaPos[nbrs[i]];
801 if (i<noc) continue;
802 u.inner_dof_indices(nbrs[i], 0, ind);
803 phi[i] = DoFRef(u,ind[0]);
804 };
805 number kappa;
806// if (computeElementCurvature2d2(kappa,noc,coord,phi,order,leastSquaresFactor)==false) UG_THROW("curvature calculation failed.\n");
807 computeElementCurvature2d(kappa,noc,coord,phi,order);
808 acEdgeCurvature[elem] = kappa;
809 }
810 elem_iterator elemIter = u.template begin<elem_type>(si);
811 elem_iterator elemIterEnd = u.template end<elem_type>(si);
812 for( ;elemIter !=elemIterEnd; ++elemIter)
813 {
814 // get Elem
815 elem_type* elem = *elemIter;
816 typename grid_type::template traits<side_type>::secure_container sides;
817 grid.associated_elements(sides, elem );
818 bool onls = false;
819 number ecurvature = 0;
820 size_t nInterSides = 0;
821 for (size_t i=0;i<sides.size();i++){
822 if (acEdgeCurvature[sides[i]]!= undefined){
823 onls = true;
824 ecurvature+=acEdgeCurvature[sides[i]];
825 nInterSides++;
826 }
827 }
828 if (onls==false) continue;
829 number kappa = (number)ecurvature/nInterSides;
830 u.dof_indices(elem,1,ind);
831 DoFRef(u,ind[0]) = kappa;
832 if (m_exactcurvatureknown==true)
833 if (std::abs(kappa+m_exactcurv)>maxnormerr){
834 maxnormerr =std::abs(kappa+m_exactcurv);
835 }
836 }
837 };
838 if (m_exactcurvatureknown==true) UG_LOG("curvature maximum error " << maxnormerr << "\n");
839 return true;
840};
841
842} // end namespace LevelSet
843} // end namespace ug
844
845/* End of File */
parameterString s
Definition Biogas.lua:2
TGridFunction::domain_type domain_type
domain type
Definition ls_curvature2d.h:50
bool computeElementCurvatureFromSides(TGridFunction &u, size_t order, number leastSquaresFactor)
Definition ls_curvature2d_impl.h:706
bool computeElementCurvature2d2(number &kappa, size_t elementnoc, const std::vector< MathVector< dim > > &co, std::vector< number > phi, size_t order, number nodefactor)
Definition ls_curvature2d_impl.h:456
bool computeElementCurvature2d(number &kappa, size_t elementnoc, const std::vector< MathVector< dim > > &co, std::vector< number > phi, size_t order)
Definition ls_curvature2d_impl.h:305
bool computeElementCurvatureOnGrid2d(TGridFunction &u, size_t order, number leastSquaresFactor)
Definition ls_curvature2d_impl.h:585
SmartPtr< TGrid > grid()
void SetAttachmentValues(TAttachmentAccessor &aaVal, TIter elemsBegin, TIter elemsEnd, const TVal &val)
void CollectNeighbors(std::vector< Edge * > &vNeighborsOut, Edge *e, Grid &grid, NeighborhoodType nbhType=NHT_VERTEX_NEIGHBORS)
void MatMultiplyMTM(MathMatrix< N, N, T > &mOut, const MathMatrix< M, N, T > &m)
#define UG_THROW(msg)
#define UG_LOG(msg)
double number
void TransposedMatVecMult(vector_t_out &vOut, const matrix_t &m, const vector_t_in &v)
vector_t::value_type VecDistance(const vector_t &v1, const vector_t &v2)
bool solveLS(std::vector< number > &x, const std::vector< number > &matField, const std::vector< number > &b)
Definition ls_curvature2d_impl.h:83
bool leastSquares(MathVector< n > &x, const MathMatrix< m, n > &M, const MathVector< m > &b)
Definition ls_curvature2d_impl.h:224
bool multMatVec(const std::vector< number > &avec, const std::vector< number > &b, std::vector< number > &c, size_t m, size_t n)
Definition ls_curvature2d_impl.h:63
int bubblesort(std::vector< number > array, std::vector< int > &list)
Definition ls_curvature2d_impl.h:36
void AverageCoords(TPosition &vOut, const std::vector< TPosition > &vCornerCoords, size_t num)
averages positions by arithmetic mean
Definition ls_curvature2d_impl.h:293
const number & DoFRef(const TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)