CONFIG LIB 1.5
Configuration Files Library (by TGG 2020)
Loading...
Searching...
No Matches
airfoil.cpp
1/*********************************************************************/
2/* */
3/* Panukl package - (C) TGG 2002 */
4/* Config files library - (C) TGG 2015 */
5/* */
6/*********************************************************************/
7/* Warszawa, 2020 */
8/*********************************************************************/
9/* */
10/* File: airfoil.cpp */
11/* */
12/* Author: T.Grabowski */
13/* */
14/* Contents - airfoil class */
15/* */
16/* Last update: 24.11.2020 */
17/* */
18/*********************************************************************/
19/* */
20/* */
21
22#include <regex>
23#include <algorithm>
24
25#include "airfoil.h"
26
27using namespace std;
28
29AIRFOIL::AIRFOIL( void )
30{
31 Xd = 0;
32 Xg = 0;
33 Zd = 0;
34 Zg = 0;
35 Xf = 0;
36 Zf = 0;
37 Xrob = 0;
38 Zrob = 0;
39 N = 0;
40 Nf = 0;
41 Nrob = 0;
42
43 /* Types:
44 0 - PRF - PANUKL (prf1) - native PANUKL (4 columns) format \n
45 1 - PRF - prf2 - by L.Wiechers- NAME in header, N below header \n
46 2 - KOO - koordinate by L.Wiechers \n
47 3 - DAT - SELIG - (Xfoil) \n
48 4 - DAT - LEDNICER
49 */
50
51 iType = 0;
52 iReadType = 0;
53 memset( cName, 0, 100 );
54}
55
56void AIRFOIL::Clean( void )
57{
58 DELETE_TAB( Xd );
59 DELETE_TAB( Xg );
60 DELETE_TAB( Zd );
61 DELETE_TAB( Zg );
62 DELETE_TAB( Xf );
63 DELETE_TAB( Zf );
64 DELETE_TAB( Xrob );
65 DELETE_TAB( Zrob );
66 N = 0;
67 Nf = 0;
68 Nrob = 0;
69 iType = 0;
70 memset( cName, 0, 100 );
71}
72
73int AIRFOIL::Read( char *cFile )
74{
75 Clean();
76
77 fprintf(stderr,"iReadType %d\n",iReadType);
78 if( iReadType )
79 getiTypeByContent(cFile); // gets file type by content
80 if( iReadType == 0 || iType == -1 )
81 getiTypeByExt(cFile); // gets file type by extension
82
83 // in case no type was detected finish
84 if(iType==-1)
85 {
86 fprintf(stderr,"No correct file was provided!\n");
87 return -1;
88 }
89
90 fprintf(stderr, "airfoil %s type %d\n", cFile, iType );
91
92 switch( iType )
93 {
94 default:
95 case 0:
96 if( Read_PRF_0( cFile ) )return -1;
97 break;
98 case 1:
99 if( Read_PRF_1( cFile ) )return -1;
100 break;
101 case 2:
102 if( Read_KOO( cFile ) )return -1;
103 break;
104 case 3:
105 if( Read_DAT( cFile ) )return -1;
106 break;
107 case 4:
108 if( Read_DAT_LEDNICER( cFile ) )return -1;
109 break;
110 }
111
112 return 0;
113}
114
115int AIRFOIL::Write( char *cFile, int iTyp )
116{
117 switch( iTyp )
118 {
119 default:
120 case 0:
121 if( Write_PRF( cFile ) )return -1;
122 break;
123/* case 1:
124 if( Write_PRF_1( cFile ) )return -1;
125 break;
126 case 2:
127 if( Write_KOO( cFile ) )return -1;
128 break;
129*/ case 3:
130 if( Write_DAT( cFile ) )return -1;
131 break;
132 }
133
134 return 0;
135}
136
137int AIRFOIL::ReadNaca( long int iNACA, int NN )
138{
139 char cNACA[10];
140 sprintf(cNACA, "%04ld", iNACA );
141 return ReadNaca( cNACA );
142}
143
144int AIRFOIL::ReadNaca( char *cNACA, int NN )
145{
146 sprintf(cName, "NACA %s", cNACA );
147
148 NACA_PROFILE *NacaProfile = new NACA_PROFILE();
149 NacaProfile->setTE0( 1 );
150 NacaProfile->generate_naca( cNACA, NN );
151
152 Nf = NacaProfile->N;
153 Xf = new double[Nf+1];
154 Zf = new double[Nf+1];
155
156 for( int i=0; i<Nf; i++ )
157 {
158 Xf[i] = NacaProfile->X[i];
159 Zf[i] = NacaProfile->Z[i];
160 }
161
162 DELETE_(NacaProfile);
163
164 XFOIL2PRF();
165
166 return 0;
167}
168
169/*
170 Gets iType based on file content (by Anna Sima) - private
171*/
172void AIRFOIL::getiTypeByContent(char *cFile)
173{
174 iType = -1; // type not yet found
175
176 FILE *ff = fopen( cFile, "r" );
177
178 // set of useful regex expressions
179 // \\d - digit
180 // \\s - whitespace
181 // + - one or more occurences
182 // * - zero or more occurences
183 // [] - match one from inside
184 // (\\+|-)? - possible + or minues - one or zero times
185 // . - whatever character
186 regex integer("\\s*\\d+\\s*"); // positive integer
187 regex number("\\s*(\\+|-)?[\\d\\.]+\\s*"); // 1 22 1.2 0.2 .2 2. - any number
188 regex prfHeader("\\d+\\s+#\\s+.+"); // number_of_lines # name (e.g. "18 # NACA 0012 ")
189 regex kooHeader(".+\\s+,\\s+\\d+"); // name , number_of_lines-1
190 regex datNLines("\\s*\\d+\\.\\s*\\d+\\.\\s*"); // 31. 31.
191 regex twoCols ("\\s*(\\+|-)?[\\d\\.]+\\s+(\\+|-)?[\\d\\.]+\\s*"); //number whitespaces(\s) number
192 regex threeCols("\\s*(\\+|-)?[\\d\\.]+\\s+(\\+|-)?[\\d\\.]+\\s+(\\+|-)?[\\d\\.]+\\s*");
193 regex fourCols ("\\s*(\\+|-)?[\\d\\.]+\\s+(\\+|-)?[\\d\\.]+\\s+(\\+|-)?[\\d\\.]+\\s+(\\+|-)?[\\d\\.]+\\s*");
194
195 // read first line
196 // PRF
197 // HEADER - number_of_lines # name
198 // [4 cols]
199 // * values 0-100
200 // if first line matches full HEADER or just number of lines
201 ReadStr( ff, cc);
202 if(regex_match(cc,prfHeader)||regex_match(cc,integer))
203 {
204 int N;
205 fseek(ff,0, SEEK_SET); // go to beginning
206 ReadPar( ff, "%d", &N );
207
208 // check number of lines
209 if(nLines( ff )!=N)
210 {
211 sprintf(comment,"Number of lines is incorrect, should be %d\n",N);
212 fprintf(stderr,"Number of lines is incorrect, should be %d\n",N);
213 if(iGUI) alert( comment );
214 iType=-1;
215 }
216 else
217 {
218 iType = 0; // assume it is ok
219 // check all further lines
220 for(int i=0; i<N; i++)
221 {
222 ReadStr( ff, cc );
223 if(!regex_match(cc,fourCols))
224 {
225 // one of the lines is incorrect
226 sprintf(comment,"%s - line incorrect!\n",cc);
227 fprintf(stderr,"%s - line incorrect!\n",cc);
228 if(iGUI) alert( comment );
229 iType=-1; // set to nok
230 break;
231 }
232 }
233 }
234 }
235
236 // PRF 2
237 // HEADER1 - numer "1" or "2"
238 // HEADER2 - number_of_lines
239 // [2 cols] or [3 cols]
240 // * values 0-100
241 if(iType==-1) // // not yet found?
242 {
243 fseek(ff,0, SEEK_SET); // go to beginning
244 ReadStr( ff, cc);
245 // first line is a number, can be whatever - read second line then
246 ReadStr( ff, cc);
247 // second line must be integer - number of lines
248 if(regex_match(cc,integer))
249 {
250 N = atoi(cc); // convert second line to integer
251 if(nLines( ff )!=N)
252 {
253 sprintf(comment,"Number of lines is incorrect, should be %d\n",N);
254 fprintf(stderr,"Number of lines is incorrect, should be %d\n",N);
255 if(iGUI) alert( comment );
256 iType=-1;
257 }
258 else
259 {
260 iType = 1; // assume type is PRF 2
261 // check all lines match format of two or three columns
262 for(int i=0; i<N; i++)
263 {
264 ReadStr( ff, cc );
265 if(!regex_match(cc,twoCols)&&!regex_match(cc,threeCols))
266 {
267 // one of the lines is incorrect
268 sprintf(comment,"%s - line incorrect!\n",cc);
269 fprintf(stderr,"%s - line incorrect!\n",cc);
270 if(iGUI) alert( comment );
271 iType=-1; // set to nok
272 break;
273 }
274 }
275 }
276 }
277 }
278
279 // KOO
280 // HEADER - name , number_of_lines-1
281 // [2 cols]
282 // * values 0-100
283 if(iType==-1) // not yet found?
284 {
285 fseek(ff,0, SEEK_SET); // go to beginning
286 ReadStr( ff, cc );
287 // check if header matches koo - name , number_of_line
288 if(regex_match(cc,kooHeader))
289 {
290 //get number of lines
291 int iLen = strlen( cc );
292 // replace all characters with whitespace till ,
293 for( int i=0; i<iLen; i++ )
294 {
295 if(cc[i]==',' )
296 {
297 cc[i]=' ';
298 break;
299 }
300 cc[i]=' ';
301 }
302 // convert spaces + number of lines string to number
303 N = atoi(cc);
304 if(nLines( ff )!=N+1)
305 {
306 sprintf(comment,"Number of lines is incorrect, should be %d\n",N);
307 fprintf(stderr,"Number of lines is incorrect, should be %d\n",N);
308 if(iGUI) alert( comment );
309 iType=-1;
310 }
311 else
312 {
313 iType=2;
314 }
315 }
316 }
317
318 // DAT - selig
319 // HEADER - name
320 // [2 cols]
321 // * values 0.0-1.0
322 if(iType==-1) // not yet found?
323 {
324 fseek(ff,0, SEEK_SET); // go to beginning
325 ReadStr( ff, cc );
326 N = nLines( ff );
327 // valide or further lines
328 iType = 3; // assume type is DAT selig
329 for(int i=0; i < N/2; i++)
330 {
331 ReadStr( ff, cc );
332 if(!regex_match(cc,twoCols))
333 {
334 sprintf(comment,"%s - line incorrect(3)!\n",cc);
335 fprintf(stderr,"%s - line incorrect(3)!\n",cc);
336 if(iGUI) alert( comment );
337 iType=-1;
338 break;
339 }
340 }
341 }
342
343 // DAT - lednicer
344 // HEADER - name
345 // HEADER - number_of_lines. number_of_lines.
346 // [empty line]
347 // [2 cols]
348 // [empty line]
349 // [2 cols]
350 // * values from 0 to 1
351 if(iType==-1) // not yet found?
352 {
353 fseek(ff,0, SEEK_SET); // go to beginning
354 N = nLines( ff ); // get number of lines
355 ReadStr( ff, cc ); // name - whatever value, ignore comparison
356 ReadStr( ff, cc ); // should be number_of_lines. number_of_lines.
357 if(regex_match(cc,datNLines))
358 {
359 fseek(ff,0, SEEK_SET); // go to beginnig
360 ReadStr( ff, cc ); // omit first line
361 float f1,f2;
362 int n1,n2;
363 ReadPar(ff, "%f %f",&f1,&f2);
364 n1 = f1;
365 n2 = f2;
366 if(N!=n1+n2+2)
367 {
368 sprintf(comment,"Number of lines incorrect, should be %d, is %d\n",N,n1+n2);
369 fprintf(stderr,"Number of lines incorrect, should be %d, is %d\n",N,n1+n2);
370 if(iGUI) alert( comment );
371 iType=-1;
372 }
373 else
374 {
375 iType=4; // assume it is lednicer
376 for(int i=0; i < N; i++)
377 {
378 ReadStr( ff, cc );
379 //string sc=cc;
380 //if(!regex_match(cc,twoCols) && !sc.empty() && !IsBlank(sc) )
381 if(!regex_match(cc,twoCols) && cc[0]!='\0' )
382 {
383 // ommit empty lines - lines == \0
384 sprintf(comment,"%s - line incorrect!\n",cc);
385 fprintf(stderr,"%s - line incorrect!\n",cc);
386 if(iGUI) alert( comment );
387 iType=-1;
388 break;
389 }
390 }
391 }
392 }
393 }
394
395 fclose(ff);
396
397}
398/*
399 Gets iType based on file extension
400*/
401void AIRFOIL::getiTypeByExt(char *cFile)
402{
403 const char *pext = filename_ext( (const char*)cFile );
404 char ext[4];
405 for(int i=0; i<3; i++)ext[i] = toupper( pext[i+1] );
406 ext[3] = '\0';
407
408 //fprintf(stderr,"cfile %s pext %s\n",cFile,pext);
409 fprintf( stderr, "ext %s\n", ext );
410
411 if( strcmp( ext, "PRF" ) == 0 )
412 {
413 iType = 0;
414 FILE *ff = fopen( cFile, "r" );
415 if( ff )
416 {
417 int N;
418 ReadPar( ff, "%d", &N );
419 int NN = nLines( ff );
420 if( N != NN )iType = 1;
421 //fprintf( stderr, "N %d NN %d typ %d\n", N, NN, iType );
422 fclose( ff );
423 }
424 else
425 iType=-1;
426 }
427 else if( strcmp( ext, "KOO" ) == 0 )
428 {
429 iType = 2;
430 }
431 else if( strcmp( ext, "DAT" ) == 0 )
432 {
433 // If both first numeric values are greater than 1, the file is lednicer format
434 iType = 3;
435 FILE *ff = fopen( cFile, "r" );
436 if( ff )
437 {
438 char cc[512];
439 int iLen = 0;
440 double topCoords, bottomCoords;
441 // header - name
442 ReadStrL( ff, cc, &iLen );
443 // first line with numbers
444 ReadPar( ff, "%lf %lf", &topCoords, &bottomCoords );
445
446 if( topCoords > 1 && bottomCoords > 1 ) iType = 4;
447 fclose( ff );
448 }
449 else
450 iType=-1;
451 }
452 else
453 iType=-1;
454
455}
456
457// Reads particular formats - private
458
459int AIRFOIL::Read_PRF_0( char *cFile )
460{
461 FILE *ff;
462 ff = fopen( cFile, "r" );
463 if( ff == NULL )
464 {
465 sprintf( comment, "File: %s not found!\n", cFile );
466 fprintf( stderr, "File: %s not found!\n", cFile );
467 if(iGUI) alert( comment );
468 return -1;
469 }
470
471 ReadPar( ff, "%d", &N );
472 Xg = new double[N];
473 Xd = new double[N];
474 Zg = new double[N];
475 Zd = new double[N];
476
477 for(int i=0; i<N; i++)
478 ReadPar( ff, "%lf %lf %lf %lf", &Xg[i], &Zg[i], &Xd[i], &Zd[i] );
479 fclose( ff );
480
481 double dAd = dAverage( Zd, N );
482 double dAg = dAverage( Zg, N );
483 if( dAg < dAd )
484 {
485 ff = fopen( cFile, "r" );
486 ReadPar( ff, "%d", &N );
487
488 for(int i=0; i<N; i++)
489 ReadPar( ff, "%lf %lf %lf %lf", &Xd[i], &Zd[i], &Xg[i], &Zg[i] );
490 fclose( ff );
491 }
492
493 double dCa = max( tabmax( Xd, N ), tabmax( Xg, N ) );
494 double dX0 = min( tabmin( Xd, N ), tabmin( Xg, N ) );
495
496 dCa -= dX0;
497 double dMnoz = 100./dCa;
498
499 if( dCa < 80. || dCa > 120. )
500 for(int i=0; i<N; i++)
501 {
502 Xg[i] *= dMnoz;
503 Zg[i] *= dMnoz;
504 Xd[i] *= dMnoz;
505 Zd[i] *= dMnoz;
506 }
507/*
508 fprintf(stderr, "\nprofil z pliku: %s\n", cFile );
509 for(int i=0; i<N; i++)
510 fprintf( stderr, "%lf %lf %lf %lf\n", Xg[i], Zg[i], Xd[i], Zd[i] );
511*/
512 TE_correct();
513
514 int iN = strlen( filename_name( cFile ) ) - 4;
515 strncpy( cName, filename_name( cFile ), iN );
516 cName[ iN ] = '\0';
517
518// fprintf(stderr, "\nnazwa: %s\n", cName );
519
520 PRF2XFOIL();
521
522 return 0;
523}
524
525int AIRFOIL::Read_PRF_1( char *cFile )
526{
527 FILE *ff;
528 ff = fopen( cFile, "r" );
529 if( ff == NULL )
530 {
531 sprintf( comment, "File: %s not found!\n", cFile );
532 fprintf( stderr, "File: %s not found!\n", cFile );
533 if(iGUI) alert( comment );
534 return -1;
535 }
536
537 int iTyp = 2;
538 ReadPar( ff, "%d", &iTyp );
539 ReadPar( ff, "%d", &Nrob );
540 Xrob = new double[2*Nrob];
541 Zrob = new double[2*Nrob];
542 Nf = Nrob;
543 if( iTyp == 1 ) Nf = Nf*2 - 1;
544 Xf = new double[Nf];
545 Zf = new double[Nf];
546
547 if( iTyp == 1 )
548 {
549 int i =0;
550 ReadPar( ff, "%lf %lf %lf", &Xrob[i], &Zrob[i], &Zrob[Nrob] );
551 Xf[i] = Xrob[i];
552 Zf[i] = Zrob[i];
553 for(i=1; i<Nrob; i++)
554 {
555 ReadPar( ff, "%lf %lf %lf", &Xrob[i], &Zrob[i], &Zrob[i+Nrob-1] );
556 Xf[i] = Xrob[i];
557 Zf[i] = Zrob[i];
558 Xf[i+Nrob-1] = Xrob[i+Nrob-1] = Xrob[i];
559 Zf[i+Nrob-1] = Zrob[i+Nrob-1];
560 }
561 Nrob = Nrob*2 - 1;
562 }
563 else
564 {
565 for(int i=0; i<Nrob; i++)
566 {
567 ReadPar( ff, "%lf %lf", &Xrob[i], &Zrob[i] );
568 Xf[i] = Xrob[i];
569 Zf[i] = Zrob[i];
570 }
571 }
572/*
573 fprintf(stderr,"Nrob = %d Nf %d\n",Nrob,Nf);
574 for(int i=0; i<Nrob; i++ )
575 fprintf(stderr,"%lf %lf \n",Xrob[i],Zrob[i]);
576*/
577 fclose( ff );
578
579 int iN = strlen( filename_name( cFile ) ) - 4;
580 strncpy( cName, filename_name( cFile ), iN );
581 cName[ iN ] = '\0';
582
583 double *Xfrob = new double[Nrob];
584 for( int i=0; i<Nrob; i++ )Xfrob[i] = Xrob[i];
585 N = Nrob;
586 SortClean( &N, Xfrob );
587
588 int nmax = N;
589 int nmin = N;
590 double dCa = dMaxT( Xrob, &nmax );
591 double dX0 = dMinT( Xrob, &nmin );
592
593 dCa -= dX0;
594 double dMnoz = 100./dCa;
595
596 int NN = nmax;
597
598 for( int i=Nrob; i>NN+1; i-- )
599 {
600 Xrob[i] = Xrob[i-1];
601 Zrob[i] = Zrob[i-1];
602 }
603 Xrob[NN+1] = Xrob[0];
604 Zrob[NN+1] = Zrob[0];
605 Nrob++;
606
607 Xg = new double[N];
608 Xd = new double[N];
609 Zg = new double[N];
610 Zd = new double[N];
611 for( int i=0; i<N; i++ )
612 {
613 Xd[i] = Xfrob[i];
614 Zd[i] = inter1( &Xrob[NN+1], &Zrob[NN+1], Nrob-NN-1, Xd[i] );
615 Xg[i] = Xd[i];
616 Zg[i] = inter1( Xrob, Zrob, NN+1, Xg[i] );
617 }
618
619 for( int i=0; i<N; i++ )
620 {
621 Xg[i] -= dX0;
622 Xg[i] *= dMnoz;
623 Xd[i] -= dX0;
624 Xd[i] *= dMnoz;
625 Zg[i] *= dMnoz;
626 Zd[i] *= dMnoz;
627 }
628
629 TE_correct();
630
631// Print( stderr );
632
633 //PRF2XFOIL();
634 int nf2 = 0;
635 while( Xf[nf2] < Xf[nf2+1] && nf2 < Nf )nf2++;
636 Sort2( nf2+1, Xf, Zf, -1 );
637 for( int i=0; i<Nf; i++ )
638 {
639 Xf[i] -= dX0;
640 Xf[i] *= dMnoz/100.;
641 Zf[i] *= dMnoz/100.;
642 }
643 DELETE_TAB( Xfrob );
644 return 0;
645}
646
647void AIRFOIL::PRF2XFOIL( void )
648{
649 Nf = 2*N - 1;
650 Xf = new double[Nf];
651 Zf = new double[Nf];
652 for(int i=0; i<N; i++)
653 {
654 Xf[i] = Xd[N-1-i]/100.;
655 Zf[i] = Zd[N-1-i]/100.;
656 }
657 for(int i=N; i<Nf; i++)
658 {
659 Xf[i] = Xg[i-N+1]/100.;
660 Zf[i] = Zg[i-N+1]/100.;
661 }
662}
663
664int AIRFOIL::Write_PRF( char *cFile )
665{
666 FILE *ff;
667 ff = fopen( cFile, "w" );
668 fprintf(ff,"%d\t#\t%s\n", N, cName );
669 for( int i=0; i<N; i++ )
670 fprintf( ff, "%f %f %f %f\n", Xg[i], Zg[i], Xd[i], Zd[i] );
671 fclose(ff);
672
673 return 0;
674}
675
676int AIRFOIL::Read_KOO( char *cFile )
677{
678 return Read_DAT( cFile );
679}
680
681void AIRFOIL::Print( FILE* f ) {
682
683 fprintf(f,"%d\t#\t%s\n", N, cName );
684 for( int i=0; i<N; i++ )
685 fprintf(f,"%f %f %f %f\n", Xg[i], Zg[i], Xd[i], Zd[i] );
686
687}
688
689int AIRFOIL::Read_DAT_LEDNICER( char *cFile ) // by Anna Sima
690{
691
692 FILE *ff;
693 ff = fopen( cFile, "r" );
694 if( ff == NULL )
695 {
696 sprintf( comment, "File: %s not found!\n", cFile );
697 fprintf( stderr, "File: %s not found!\n", cFile );
698 if(iGUI) alert( comment );
699 return -1;
700 }
701//reads 1st line - profile name
702 ReadStr( ff, cName );
703
704 float f1, f2;
705 int rowsPos, rowsNeg;
706
707 ReadPar(ff, "%f %f", &f1, &f2);
708 rowsPos = f1;
709 rowsNeg = f2;
710
711//makes empty arrays to store values from the file
712 Xf = new double[rowsPos+rowsNeg];
713 Zf = new double[rowsPos+rowsNeg];
714
715 Nf = rowsPos+rowsNeg-1; //total number of points(rows) that will be in the end
716
717 for( int i=rowsPos-1; i>=0; i-- ) {
718 ReadPar(ff, "%lf %lf",&Xf[i],&Zf[i]); //read all upper
719 }
720
721 for( int i=0; i<rowsNeg; i++ ) {
722 ReadPar(ff, "%lf %lf",&Xf[rowsPos-1 + i],&Zf[rowsPos-1 + i]); //read all lower
723 }
724
725 fclose( ff );
726
727 Check( &Nf, Xf, Zf );
728
729 XFOIL2PRF();
730
731 return 0;
732}
733
734int AIRFOIL::Read_DAT( char *cFile )
735{
736 FILE *ff;
737 ff = fopen( cFile, "r" );
738 if( ff == NULL )
739 {
740 sprintf( comment, "File: %s not found!\n", cFile );
741 fprintf( stderr, "File: %s not found!\n", cFile );
742 if(iGUI) alert( comment );
743 return -1;
744 }
745
746 Nf = nLines( ff ) - 1;
747 fclose( ff );
748 if( Nf < 6 )
749 {
750 sprintf( comment, "File: %s - the number of rows is too small!\n", cFile );
751 fprintf( stderr, "File: %s - the number of rows is too small!\n", cFile );
752 if(iGUI) alert( comment );
753 return -1;
754 }
755
756 Xf = new double[Nf+1];
757 Zf = new double[Nf+1];
758 ff = fopen( cFile, "r" );
759 ReadStr( ff, cName );
760 if( iType == 2 )
761 {
762 int iLen = strlen( cName );
763 for( int i=iLen; i>0; i-- )if( cName[i] == ',' )cName[i] = '\0';
764 }
765 for( int i=0; i<Nf; i++ )
766 if( iType == 2 )
767 {
768 ReadStr( ff, cc );
769 for( int ii=0; ii < (int)strlen( cc ); ii++)if( cc[ii] == ',' )cc[ii] = ' ';
770 sscanf( cc, "%lf %lf", &Xf[i], &Zf[i] );
771 }
772 else
773 if( ReadPar( ff, "%lf %lf", &Xf[i], &Zf[i] ) == EOF )
774 {
775 Nf = i;
776 break;
777 };
778 fclose( ff );
779
780 Check( &Nf, Xf, Zf );
781
782 XFOIL2PRF();
783
784 return 0;
785}
786
787void AIRFOIL::XFOIL2PRF( void )
788{
789 int nmax = Nf;
790 int nmin = Nf;
791 double dCa = dMaxT( Xf, &nmax );
792 double dX0 = dMinT( Xf, &nmin );
793 //fprintf(stderr,"Xf min %f %f %f\n",Xf[nmin-1],Xf[nmin],Xf[nmin+1]);
794
795 if( Xf[nmin-1] == Xf[nmin] ) // nose correction
796 {
797 double XX[4], YY[4];
798 for( int i=0; i<4; i++)
799 {
800 XX[i]=Xf[nmin-2+i];
801 YY[i]=Zf[nmin-2+i];
802 }
803 double Y0 = 0.5*(YY[2]+YY[1]);
804 double X0 = apr3( Y0, YY, XX );
805 for( int i=Nf; i>nmin; i-- )
806 {
807 Xf[i] = Xf[i-1];
808 Zf[i] = Zf[i-1];
809 }
810 Xf[nmin] = X0;
811 Zf[nmin] = Y0;
812 Nf++;
813 nmax = Nf;
814 nmin = Nf;
815 dCa = dMaxT( Xf, &nmax );
816 dX0 = dMinT( Xf, &nmin );
817 }
818 dCa -= dX0;
819 double dMnoz = 100./dCa;
820
821 double dW1, dW2;
822 int iSter = 0; // 1 - lower surface first, 0 - upper surface first
823 int NN = min( nmin, nmax );
824 if( nmax > nmin || nmax == 0 )
825 {
826 dW1 = dAverage( Zf, nmin );
827 dW2 = dAverage( &Zf[nmin], Nf - nmin );
828 if( dW2 > dW1 )iSter = 1;
829 NN = nmin;
830 }
831 else
832 {
833 dW1 = dAverage( Zf, nmax );
834 dW2 = dAverage( &Zf[nmax], nmin - nmax );
835 if( dW2 > dW1 )iSter = 1;
836 NN = nmax;
837 }
838
839 fprintf( stderr, "ReadDAT - Xfoil2Prf:\n" );
840 fprintf( stderr, "Nf = %d NN = %d iSter = %d\n", Nf, NN, iSter );
841 fprintf( stderr, "max %d min %d\n", nmax, nmin );
842 fprintf( stderr, "X0 %f Ca %f\n", dX0, dCa );
843 fflush( stderr );
844
845 double *Xfrob = new double[Nf];
846 for( int i=0; i<Nf; i++ )Xfrob[i] = Xf[i];
847 N = Nf;
848 SortClean( &N, Xfrob );
849
850 Xg = new double[N];
851 Xd = new double[N];
852 Zg = new double[N];
853 Zd = new double[N];
854 if(iSter == 1)
855 {
856 for( int i=0; i<N; i++ )
857 {
858 Xd[i] = Xfrob[i];
859 Zd[i] = inter1( Xf, Zf, NN+1, Xd[i] );
860 Xg[i] = Xd[i];
861 Zg[i] = inter1( &Xf[NN], &Zf[NN], Nf-NN, Xg[i] );
862 }
863 }
864 else
865 {
866 for( int i=0; i<N; i++ )
867 {
868 Xd[i] = Xfrob[i];
869 Zd[i] = inter1( &Xf[NN], &Zf[NN], Nf-NN, Xd[i] );
870 Xg[i] = Xd[i];
871 Zg[i] = inter1( Xf, Zf, NN+1, Xg[i] );
872 }
873 }
874
875 for( int i=0; i<N; i++ )
876 {
877 Xg[i] -= dX0;
878 Xg[i] *= dMnoz;
879 Xd[i] -= dX0;
880 Xd[i] *= dMnoz;
881 Zg[i] *= dMnoz;
882 Zd[i] *= dMnoz;
883 }
884
885 TE_correct();
886
887 for( int i=0; i<Nf; i++ )
888 {
889 Xf[i] -= dX0;
890 Xf[i] *= dMnoz/100.;
891 Zf[i] *= dMnoz/100.;
892 }
893
894}
895
896int AIRFOIL::Write_DAT( char *cFile )
897{
898 FILE *ff;
899 ff = fopen( cFile, "w" );
900 fprintf(ff,"%s\n", cName );
901 for( int i=0; i<Nf; i++ )
902 fprintf( ff, " %f %f \n", Xf[i], Zf[i] );
903 fclose(ff);
904
905 return 0;
906}
907
908void AIRFOIL::TE_correct( void )
909{
910 double zz = 0.5*(Zd[N-1]+Zg[N-1]);
911 Zd[N-1] = Zg[N-1] = zz;
912}
913
914// math routines
915
916double AIRFOIL::dAverage( double *dTab, int i1 )
917{
918 double dSum = 0.;
919 for( int i=0; i<i1; i++) dSum += dTab[i];
920 dSum = dSum / i1;
921
922 return (dSum);
923}
924
925double AIRFOIL::tabmax( double* dTab, int n )
926{
927 double dWyn = dTab[0];
928 if(n>1)for( int i=1; i<n; i++ )dWyn = max( dWyn, dTab[i] );
929 return dWyn;
930}
931
932double AIRFOIL::tabmin( double* dTab, int n )
933{
934 double dWyn = dTab[0];
935 if(n>1)for( int i=1; i<n; i++ )dWyn = min( dWyn, dTab[i] );
936 return dWyn;
937}
938
939double AIRFOIL::dMaxT( double *dTab, int *i1 )
940{
941 int n = *i1;
942 *i1 = 0;
943 double dRob = dTab[0];
944 for( int i=0; i<n; i++)
945 {
946 dRob = max( dTab[i], dRob );
947 if( dRob == dTab[i] )*i1 = i;
948 }
949 return (dRob);
950}
951
952double AIRFOIL::dMinT( double *dTab, int *i1 )
953{
954 int n = *i1;
955 *i1 = 0;
956 double dRob = dTab[0];
957 for( int i=0; i<n; i++)
958 {
959 dRob = min( dTab[i], dRob );
960 if( dRob == dTab[i] )*i1 = i;
961 }
962 return (dRob);
963}
964
965void AIRFOIL::Check( int *nn, double *X, double *Z )
966{
967 N = *nn;
968 for(int i=0; i<N-1; i++)
969 {
970 if( X[i] == X[i+1] && Z[i] == Z[i+1] )
971 {
972 for( int ii=i; ii<N-1; ii++ )
973 {
974 X[ii]=X[ii+1];
975 Z[ii]=Z[ii+1];
976 }
977 N--;
978 }
979 }
980 *nn = N;
981}
982
983unsigned long AIRFOIL::locate(double xx[], unsigned long n, double x )
984{
985 unsigned long j;
986 unsigned long ju,jm,jl;
987
988 int ascnd;
989 ascnd = ( xx[n-1] >= xx[0] );
990
991 if( ascnd )
992 {
993 if( x <= xx[0] )
994 j = 0;
995 else if ( x >= xx[n-1] )
996 j = n - 2;
997 else
998 {
999 jl = 0;
1000 ju = n;
1001 while ( ju-jl > 1)
1002 {
1003 jm = (ju+jl) >> 1; // midpoint (ju+jl)/2
1004 if( (x >= xx[jm]) == ascnd)
1005 jl=jm;
1006 else
1007 ju=jm;
1008 }
1009 j = jl;
1010 }
1011 }
1012 else
1013 {
1014 if( x >= xx[0] )
1015 j = 0;
1016 else if ( x <= xx[n-1] )
1017 j = n - 2;
1018 else
1019 {
1020 jl = 0;
1021 ju = n;
1022 while ( ju-jl > 1)
1023 {
1024 jm = (ju+jl) >> 1; // midpoint (ju+jl)/2
1025 if( (x >= xx[jm]) == ascnd)
1026 jl=jm;
1027 else
1028 ju=jm;
1029 }
1030 j = jl;
1031 }
1032 }
1033
1034 return j;
1035
1036}
1037
1038/*
1039 linear interpolation for one-dimensional array (no extrapolation)
1040*/
1041
1042double AIRFOIL::inter1(double *xx, double *yy, unsigned long n, double x )
1043{
1044 unsigned long numer;
1045 double y;
1046
1047 if( (xx[n-1]-xx[0]) < 0. )
1048 {
1049 x = min( x, xx[0] );
1050 x = max( x, xx[n-1] );
1051 }
1052 else
1053 {
1054 x = max( x, xx[0] );
1055 x = min( x, xx[n-1] );
1056 }
1057 numer = locate(xx, n, x );
1058 //double aa = (yy[numer+1]-yy[numer])/(xx[numer+1]-xx[numer]);
1059 //double bb = yy[numer] - aa*xx[numer];
1060 //y = aa*x + bb;
1061
1062 y = yy[numer+1]*(x-xx[numer]) + yy[numer]*(xx[numer+1]-x);
1063 y /= xx[numer+1]-xx[numer];
1064
1065
1066 return y;
1067}
1068
1069double AIRFOIL::apr3( double dX, double *dXX, double *dYY )
1070{
1071 double X1 = dXX[0];
1072 double X2 = dXX[1];
1073 double X3 = dXX[2];
1074 double X4 = dXX[3];
1075 double F1 = dYY[0];
1076 double F2 = dYY[1];
1077 double F3 = dYY[2];
1078 double F4 = dYY[3];
1079
1080 double X13 = pow( X1, 3.0 );
1081 double X23 = pow( X2, 3.0 );
1082 double X33 = pow( X3, 3.0 );
1083 double X43 = pow( X4, 3.0 );
1084
1085 double Q1 = X33*(X2-X1) - X23*(X3-X1) + X13*(X3-X2);
1086 double Q2 = X43*(X2-X1) - X23*(X4-X1) + X13*(X4-X2);
1087 double Q3 = (X3-X2)*(X2-X1)*(X3-X1);
1088 double Q4 = (X4-X2)*(X2-X1)*(X4-X1);
1089 double Q5 = F3*(X2-X1) - F2*(X3-X1) + F1*(X3-X2);
1090 double Q6 = F4*(X2-X1) - F2*(X4-X1) + F1*(X4-X2);
1091
1092 double a3 = (Q3*Q6-Q4*Q5)/(Q2*Q3-Q1*Q4);
1093 double a2 = (Q5-a3*Q1)/Q3;
1094 double a1 = (F2-F1)/(X2-X1) - a3*(X23-X13)/(X2-X1) - a2*(X1+X2);
1095 double a0 = F1 - a1*X1 - a2*X1*X1 - a3*X13;
1096
1097 return( a0 + a1*dX + a2*dX*dX + a3*dX*dX*dX );
1098}
1099
1100//
1101// Sorting routine with deleting the same values
1102//
1103
1104void AIRFOIL::SortClean( int *N, double *X )
1105{
1106 int NN = *N;
1107 Sort1( NN, X );
1108 for( int i=0; i<NN-1; i++ )
1109 {
1110 if( X[i] == X[i+1] )
1111 {
1112 for( int ii=i; ii<NN-1; ii++ )X[ii]=X[ii+1];
1113 NN--;
1114 }
1115 }
1116 *N = NN;
1117}
1118
1119//
1120// Simply sorting routine
1121//
1122
1123void AIRFOIL::Sort1( int N, double dRA[] )
1124{
1125 double T;
1126 int i,j,k;
1127
1128 k = N;
1129 while( k > 1 )
1130 {
1131 k = k/2;
1132 for( j=0; j<(N-k); j++ )
1133 for( i=j; i>=0; i-=k )
1134 {
1135 if( dRA[i] > dRA[i+k] )
1136 {
1137 T = dRA[i];
1138 dRA[i] = dRA[i+k];
1139 dRA[i+k] = T;
1140 }
1141 }
1142 }
1143}
1144
1145
1146bool AIRFOIL::check_order( double d1, double d2, int iFlag )
1147{
1148 if( iFlag >= 0 )
1149 return ( d1 < d2 );
1150 else
1151 return ( d1 > d2 );
1152}
1153
1154//
1155// Sorting routine with ordering 2nd array
1156//
1157
1158void AIRFOIL::Sort2( int iN, double dRA[], double dKOL[], int iOrder )
1159{
1160
1161 double dRRA, dRA2;
1162 int i,j,l,iR;
1163
1164 l = iN/2 + 1;
1165 iR = iN;
1166
1167 if( iN <= 1 ) return;
1168
1169 while( true )
1170 {
1171 if( l > 1 )
1172 {
1173 l = l - 1;
1174 dRRA = dRA[l-1];
1175 dRA2 = dKOL[l-1];
1176 }
1177 else
1178 {
1179 dRRA = dRA[iR-1];
1180 dRA2 = dKOL[iR-1];
1181 dRA[iR-1] = dRA[0];
1182 dKOL[iR-1] = dKOL[0];
1183 iR--;
1184 if( iR == 1 )
1185 {
1186 dRA[0] = dRRA;
1187 dKOL[0] = dRA2;
1188 return;
1189 }
1190 }
1191
1192 i = l;
1193 j = l + l;
1194 while( j <= iR )
1195 {
1196 if( ( j < iR ) && check_order( dRA[j-1], dRA[j], iOrder ) )j++;
1197 if( check_order( dRRA, dRA[j-1], iOrder ) )
1198 {
1199 dRA[i-1] = dRA[j-1];
1200 dKOL[i-1] = dKOL[j-1];
1201 i = j;
1202 j = j + j;
1203 }
1204 else
1205 {
1206 j = iR + 1;
1207 }
1208 //fprintf(stderr,"j=%d ir %d\n",j,iR);fflush(stderr);
1209 }
1210
1211 dRA[i-1] = dRRA;
1212 dKOL[i-1] = dRA2;
1213 }
1214
1215}
double * Xf
X coordinates (Nf points)
Definition airfoil.h:99
void Print(FILE *f=stdout)
prints PRF file (default on stdout)
Definition airfoil.cpp:681
double * Xd
X coordinates of lower contour (N points)
Definition airfoil.h:103
void Clean(void)
cleans local variables
Definition airfoil.cpp:56
int ReadNaca(long int iNACA, int NN=100)
generates NACA airfoil given by long int value (e.g. iNACA = 23012), NN - the number of points that...
Definition airfoil.cpp:137
double * Zf
Z coordinates (Nf points)
Definition airfoil.h:100
int Read(char *cFile)
reads profile file
Definition airfoil.cpp:73
int Nf
size of the vectors with geometry data - compatible with Xfoil
Definition airfoil.h:98
int Write(char *cFile, int iTyp=0)
saves profile file - two types are available: 0 - native PANUKL (4 columns) 3 - SELIG (Xfoil comp...
Definition airfoil.cpp:115
char cName[100]
filename (without path)
Definition airfoil.h:117
int iType
File type: 0 - PRF - PANUKL (prf1) - native PANUKL (4 columns) format 1 - PRF - prf2 - by L....
Definition airfoil.h:115
int N
size of the vectors with geometry data - 4 column native PANUKL format
Definition airfoil.h:102
int iGUI
GUI flag - messages displayed using wrapping function "alert".
Definition airfoil.h:93
double * Zg
Z coordinates of upper contour (N points)
Definition airfoil.h:106
void(* alert)(char *c)
virtual fuction to display the message (if iGUI > 0)
Definition airfoil.h:94
double * Zd
Z coordinates of lower contour (N points)
Definition airfoil.h:105
double * Xg
X coordinates of upper contour (N points)
Definition airfoil.h:104
static void ReadStrL(FILE *stream, char *Par, int *len)
Function to read the string (Par) from FILE "stream". It reads from current pointer of FILE to the en...
Definition iofun.cpp:216
static FILE * fopen(const char *filename, const char *mode)
Cross-platform function to fopen function that supports UTF-8 encoded name.
Definition iofun.cpp:358
static const char * filename_name(const char *name)
Returns pointer to filename without path.
Definition iofun.cpp:284
static int nLines(FILE *stream)
Returns number of lines of text file from current pointer to EOF.
Definition iofun.cpp:426
static int ReadStr(FILE *stream, char *Par)
Function to read the new line from FILE "stream" and to store it in table of char "Par"....
Definition iofun.cpp:163
static int ReadPar(FILE *stream, const char *Format, void *Par)
Function to read one variable. The type of variable depends on Format, compatible with stdio library.
Definition iofun.cpp:67
static const char * filename_ext(const char *buf)
Returns pointer to filename extension.
Definition iofun.cpp:302
NACA_PROFILE class to generate 4-digit and 5-digit naca airfoils Created by Alexandre Naaman (hoser...
Definition naca.h:69
int generate_naca(char *name, int num, FILE *fp)
generates naca airfoil coordinates (NN points) and stores it in file defined by stream "fp"
Definition naca.cpp:314
void setTE0(int TE=1)
TE=1 forces the zero thickness trailing edge.
Definition naca.h:108
double * Z
z coordinates vecotr
Definition naca.h:111
int N
coordiantes vectors' size
Definition naca.h:112
double * X
x coordinates vector
Definition naca.h:110
#define DELETE_(OBJ)
Macro for safe deleteing the object and sets the pointer to zero.
Definition memfun.h:84
#define DELETE_TAB(OBJ)
Macro for safe deleteing the array and sets the pointer to zero.
Definition memfun.h:97