Imported Upstream version 4.6.0
[debian/atlc] / src / non_gui / atlc.c
1 /*
2 atlc - arbitrary transmission line calculator, for the analysis of
3 transmission lines are directional couplers. 
4
5 Copyright (C) 2002. Dr. David Kirkby, PhD (G8WRB).
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either package_version 2
10 of the License, or (at your option) any later package_version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
20 USA.
21
22 Dr. David Kirkby, e-mail drkirkby@ntlworld.com 
23
24 */
25 #include "config.h"
26
27 #ifdef HAVE_STRING_H
28 #include <string.h>
29 #endif
30
31 #ifdef HAVE_STRINGS_H
32 #include <strings.h>
33 #endif
34
35 #ifdef HAVE_STDLIB_H
36 #include <stdlib.h>
37 #endif  
38
39 #ifdef HAVE_ERRNO_H
40 #include <errno.h>
41 #endif
42
43 #ifdef HAVE_LIMITS_H
44 #include <limits.h>
45 #endif
46
47 #include "definitions.h"
48 #include "exit_codes.h"
49
50 #ifdef ENABLE_POSIX_THREADS
51 #include <pthread.h>
52 #endif
53
54 #ifdef ENABLE_MPI
55 #include <mpi.h>
56 #endif
57
58
59 #ifdef WINDOWS
60 #pragma hrdstop
61 #include <condefs.h>
62 #endif
63
64
65
66 struct pixels Er_on_command_line[MAX_DIFFERENT_PERMITTIVITIES];
67 struct pixels Er_in_bitmap[MAX_DIFFERENT_PERMITTIVITIES];
68
69 double **Vij;
70 double **Er;
71 unsigned char **oddity; 
72 unsigned char **cell_type; 
73 unsigned char *image_data;
74 int width=-1, height=-1;
75 extern int errno;
76 int number_of_workers=MAX_THREADS; 
77 int non_vacuum_found=FALSE;
78 int dielectrics_to_consider_just_now;
79 int coupler=FALSE;
80 double r=1.90;
81
82 char *inputfile_name;
83
84 int main(int argc, char **argv) /* Read parameters from command line */
85 {
86   FILE *where_to_print_fp=stdout, *image_data_fp;
87   char *outputfile_name, *appendfile_name, *output_prefix;
88   long i;
89   size_t size;
90   int offset;
91   int q;
92   char *end;
93   struct transmission_line_properties data;
94   errno=0; 
95   set_data_to_sensible_starting_values(&data);
96   inputfile_name=string(0,1024);
97   outputfile_name=string(0,1024);
98   appendfile_name=string(0,1024);
99   output_prefix=string(0,1024);
100   /* only use this if we have both a multi-threaded application and that 
101   with have the function */
102   (void) strcpy(output_prefix,"");
103   while((q=get_options(argc,argv,"Cr:vsSc:d:p:i:t:w:")) != -1)
104   switch (q) 
105   {
106     case 'C':
107       print_copyright( (char *) "1996-2002");
108       exit_with_msg_and_exit_code("",1);
109     break;
110     case 'b':
111       data.should_binary_data_be_written_tooQ=TRUE;
112     break;
113     case 'd':
114       /* Read a colour from the command line */
115       Er_on_command_line[data.dielectrics_on_command_line].other_colour=\
116       strtol(my_optarg, &end, 16);
117       /* Sepparte it into the Red, Green and Blue components */
118       Er_on_command_line[data.dielectrics_on_command_line].blue=\
119       Er_on_command_line[data.dielectrics_on_command_line].other_colour%256;
120       Er_on_command_line[data.dielectrics_on_command_line].green=\
121       Er_on_command_line[data.dielectrics_on_command_line].other_colour/(256);
122       Er_on_command_line[data.dielectrics_on_command_line].red=\
123       Er_on_command_line[data.dielectrics_on_command_line].other_colour/(256*256);
124       end++; /* Gets rid of '=' sign which we put on the command line */
125       Er_on_command_line[data.dielectrics_on_command_line].epsilon=atof(end);
126       if (data.verbose_level > 1)
127         printf("r=%x g=%x b=%x col=%x Er=%f\n",\
128       Er_on_command_line[data.dielectrics_on_command_line].red,\
129       Er_on_command_line[data.dielectrics_on_command_line].green, \
130       Er_on_command_line[data.dielectrics_on_command_line].blue, \
131       Er_on_command_line[data.dielectrics_on_command_line].other_colour, \
132       Er_on_command_line[data.dielectrics_on_command_line].epsilon);
133       data.dielectrics_on_command_line++;
134     break;
135     case 'c':
136       data.cutoff=atof(my_optarg);
137     break;
138     case 'p':
139       (void) strcpy(output_prefix,my_optarg);
140     break;
141     case 'r':
142       data.r=atof(my_optarg);
143       r=data.r;
144     break;
145     case 's':
146       data.write_bitmap_field_imagesQ=FALSE;
147     break;
148     case 'S':
149       data.write_binary_field_imagesQ=FALSE;
150     break;
151     case 't':
152       number_of_workers=atol(my_optarg);
153       if(number_of_workers > MAXIMUM_PROCESSING_DEVICES)
154       {
155          fprintf(stderr,"You are exceeded the %d limit set in the file definitions.h\n",MAXIMUM_PROCESSING_DEVICES);
156          fprintf(stderr,"If you really do want this many, you will need to recompile\n");    
157          exit_with_msg_and_exit_code("",USER_REQUESTED_TOO_MANY_THREADS);
158       }
159 #ifndef ENABLE_POSIX_THREADS
160       if(number_of_workers != 0)
161          exit_with_msg_and_exit_code("Error #1. The -t option can not be \
162 used, (except to  set t=0, which is an \nexception made to allow a \
163 benchmark to run), on a version of atlc that was \nnot configured with the \
164 --with-threads option, and hence built without the \nthreads library.\n",1);
165 #endif
166     break;
167     case 'w':
168 #ifndef ENABLE_MPI
169       exit_with_msg_and_exit_code("Error #1a. The -w option can not be used on \
170 a version of atlc that was not\nconfigured with the --with-mpi option, \
171 hence built without the mpi\nlibrary.\n",1);
172 #endif
173           break;
174     case 'i': /* Lighten or darken images of E-field */
175           data.image_fiddle_factor=atof(my_optarg);
176           break;
177     case 'v':
178       data.verbose_level++;
179     break;
180     case '?':
181       usage_atlc();
182   } /* End of the switch statement */
183
184   /* There should only be one argument to atlc, the bitmapfile name.
185   There can be a few options though. We now check that there is only
186   one argument */
187
188   if(argc-my_optind == 1)  /* This should be so hopefully !! */
189   {
190 #ifdef DEBUG
191   if (errno != 0)
192     fprintf(stderr,"errno=%d in atlc.c #2\n",errno);
193 #endif
194     (void) strcpy(inputfile_name, argv[my_optind]);
195     (void) strcpy(outputfile_name, output_prefix);
196     (void) strcat(output_prefix,inputfile_name);
197     (void) strcpy(outputfile_name,output_prefix);
198     free_string(output_prefix,0,1024);
199     read_bitmap_file_headers(inputfile_name, &offset, &size, &width, &height);
200
201     /* Allocate all ram now, so atlc is sure to have it. There is no point
202     in getting some now, starting work then finding atlc can't get the 
203     rest of what is needed. */
204     image_data=ustring(0L,(long)size);
205     oddity=ucmatrix(0,width-1,0,height-1);
206     cell_type=ucmatrix(0,width-1,0,height-1);
207     Vij=dmatrix(0,width-1,0,height-1);
208     Er=dmatrix(0,width-1,0,height-1);
209     /* On Solaris systems, if the following is not executed, only one 
210     thread will run at any one time, which rather defeats the object of 
211     running multi-threaded. */
212
213 #ifdef ENABLE_POSIX_THREADS
214 #ifdef HAVE_PTHREAD_SETCONCURRENCY     
215     pthread_setconcurrency(number_of_workers);
216 #endif 
217 #endif 
218     
219     /* Each thread solves the equations for a part of the voltage
220     matrix. If there were more threads than columms we would have a
221     problem. I'm not sure exactly how many can be got away with, but
222     one is unlikly to have more cpus that matrix columns */
223
224     /* In theory, it would be sensible to get atlc to be able to read
225     from stdin. This is a test, that checks if the filename is '-', and
226     if so assumes its reading from stdin. So far, the program is
227     unable to read from stdin, so this code is not really doing
228     anything useful, but might be expanded at a later date. */
229 #ifdef DEBUG
230   if (errno != 0)
231     fprintf(stderr,"errno=%d in atlc.c #3\n",errno);
232 #endif
233     if( strcmp(argv[my_optind],"-") != 0)
234     {
235       if( (image_data_fp=fopen(inputfile_name, "rb")) == NULL)
236       {
237         fprintf(stderr,"Error #3. Can't open %s!!!!!\n", argv[my_optind]);
238         exit_with_msg_and_exit_code("",3);
239       }
240       if(fseek(image_data_fp, offset, SEEK_SET)!=0)
241       {   
242         fprintf(stderr,"Error #4. Sorry, unable to seek to the correct part \
243         (offset=%d) of the bmp image\n", offset);
244         exit_with_msg_and_exit_code("",4);
245       }
246     } /* end of if( strcmp(argv[my_optind],"-") != 0) */
247     else
248       image_data_fp=stdin;
249     /* For some unknown reason Microsoft's Visual C++ was unhappy to read
250     the bitmap image using an fread() call. Instead, the following two 
251     stupid lines fixed that issue. This will only get compiled under 
252     Windoze, the more sensible fread call being used on other operating 
253     systems. */
254
255 #ifdef WINDOWS
256     for(i=0; (i < (long)size ) && (feof(image_data_fp)==0); i++)
257       image_data[i]=(unsigned char)fgetc(image_data_fp);
258 #else
259         i = fread(image_data,  size, 1, image_data_fp);
260 #endif
261     if((ferror(image_data_fp) || (i != 1 )))
262     {
263       fprintf(stderr,"Error #5. Unable to read all of the image data properly\n");
264       exit_with_msg_and_exit_code("",5);
265     }
266     /* declare matrix's to indicate what pixels are fixed and variable */
267     /* We now fill the following 3 arrays with the correct data, based on the 
268     contents of the bitmap image */
269
270     setup_arrays(&data);
271     set_oddity_value();
272
273     /* If there are multiple dielectrics, the impedance calculations
274     needs to be done twice. We start by doing them once, for an vacuum
275     dielectric. If necessary, they will be done again */
276     do_fd_calculation(&data, size, where_to_print_fp,outputfile_name);
277   }
278   else
279   {
280     usage_atlc();
281     return(PROGRAM_CALLED_WITH_WRONG_NUMBER_OF_ARGUMENTS); 
282   }
283   free_string(inputfile_name,0,1024);
284   free_string(outputfile_name,0,1024);
285   free_string(appendfile_name,0,1024);
286   free_ustring(image_data,0L,(long) size);
287   free_ucmatrix(oddity,0,width-1,0,height-1);
288   free_ucmatrix(cell_type,0,width-1,0,height-1);
289   free_dmatrix(Vij, 0,width-1,0,height-1);
290   free_dmatrix(Er,0,width-1,0,height-1);
291   return(OKAY); 
292 }