![]() ![]() |
![]() |
File: [Development] / JSOC / proj / vfisv / apps / vfisv_fd10_old.c
(download)
Revision: 1.1, Tue Apr 30 19:24:43 2013 UTC (10 years, 1 month ago) by keiji Branch: MAIN CVS Tags: Ver_LATEST, Ver_9-5, Ver_9-41, Ver_9-4, Ver_9-3, Ver_9-2, Ver_9-1, Ver_9-0, Ver_8-8, Ver_8-7, Ver_8-6, Ver_8-5, Ver_8-4, Ver_8-3, Ver_8-2, Ver_8-12, Ver_8-11, Ver_8-10, Ver_8-1, HEAD *** empty log message *** |
/* ------------------------------------------------------------------------------------------------------ * * --- comments by Rick and Priya ----- * * vfisv.c ~rick/hmi/vecb/src/v09 * 3/25/10 this is Keiji's less memory usage version with my edits for keywords * and k=0. * 3/23/10 THIS IS a copy of REBECCA's /v13 except with vfisv_mpi * this is the mpi version vfisv.c version 10. It should have the keywords correct AND 12 err files. * This directory contains Rebeccas new/improved Invert code with the "scaling factor"?? * C DRMS module version of Juan Borrero's driver program dmrs.f90 * version v2.0 modified to handle input file(s) from the DRMS containing * artificial HMI data and work on the mpi. * Note the input parameters for the invert module have changed!! * * Usage: vfisv [...] * or (on new cluster): mpiexec -n # vfisv [...] * or (on old cluster): ~kehcheng/mpich2/bin/mpirun -np # vfisv_mpc [...] * * Bugs: * Facilities for inverting only part of an image are for debugging, * should be eliminated from final version, as they add unnecessray * complexity * The statistics for inverted quantities are calculated over the whole * image, not just the part inverted * Off-limb pixels are not handled well, the inversion results are set * to 0; this means that the statistics of the inverted parameters * calculated over the whole image are meaningless. * The initialization of the inversion quantities is silly, an arbitrary * one of the Stokes parameters; they should be calloc'd to 0 or (better) * NaN * 1-21-10:Added a map_param which will track which of the datapts were NaN's * and were then converted to Zero. We should not borther to waste computational * power to invert them. * There is no parameter to govern which of the quantities are inverted; * it has to be modified by changing the FREE array in map_param.f90 * and recompiling, and output files are generated for all quantities, * regardless of whether they have been calculated or not * Likewise, the QUICKLOOK, STRAYLIGHT_CALCULATION, and ERRORS parameters * are set in code (map_param.f90) * The output FITS files are floats, not scaled shorts; an entire set of * 18*imgpix values have to be allocated for assembly; it might be better * to write slices into the output FITS segments. * Can't handle case in which some data segments (e.g. a wavlength set) * are missing. * Number of threads must be a divisor of number of pixels in image; * 2**n for full HMI images; need to generalize, and allow for unequal * thread segments * * --- some comments by K.H., after March 2010 ----- * * 1) March 26, 2010 * First, combining efforts done by 5:00PM, March 26, 2010 * (a) a lot of things such as JSOC DRMS things done by Priya and Rick * /home/priya/vecb/VFISV_new/v11/vfisv.c * (b) Default parameters defined by Rebecca * /home/rce/v16/vfisv.c * (c) MPI things by Priya, Rick and K.H. * 2) March 29 * (a) added lines to handle pixels containing NaN or all-zero values in input * 3) April 2 * (b) modified DRMS part : correcting JSOC-keyword(s) including T_REC. * (c) moved lines for inversion initialization that should be done * after malloc/calloc-ings all wrapper-arrays (and just before the inverson process) * (d) modified positions and contents of printf(). * (e) modified how the argument at the command line will be taken into: * All arguments variables and flags be treated as constant in wrapper. * 4) April 16 * (a) added a feature doing only the rectangle region of interest, * being enabled by setting #define RECTANGL 1 * 5) April 20 * (a) added Sebastien's filter function, * being enabled by setting #define FILTFUNC 1 * 6) May 11 * (a) add part to take previous (and/or existing) results for initial guess, * being enabled by setting #define TAKEPREV 1 * 7) June 21 * (a) some minor tweaks at wrapper, to do process only regions of interest * enabled by turning QUICKRUN to be 1 * 8) Oct 5 * (a) accomodate the mask-data from patch clipping / automated-AR recognition algorithm * implemented in JSOC by Xudong Sun. * By setting MASKPTCH == 1, this functionality be enabled. * (b) remove the choice FILTFUNC because it will be always 1. * (c) remove the choice NEWARRAY because it will be always 1. * 9) Nov 3 * (a) handle a new variable iconverge_flag, flag/index of confidence at invert_(), by Rebecca, and * output the integer as a new segment array (named convflag). * (b) give version number 1.00 * 9')Nov 23 * (a) add line to write the version number as keyword value, and make new .jsd file * 10) Dec 9 * (a) now the all float will be rescaled so that the saved data will be of integer type. * (b) thus, making new .jsd file * (c) give version number 1.01 * 11) 2011 Jan 27 * (a) some changes/trial and tips made from Dec 10 to Jan 27, are included/controlled by preprocess. * INTBSCL, CHNGTREC pre-process flags are added. * 12) Jan 31 * (a) Minor modification around choice MASKPTCH to adjust to the Xudong's latest masking data array. * 13')Feb 03 * (a) clean up code: an unused variable npix is deleted. * 14) Feb 06 * (a) add keyword, mostly at the option argument * 15) Feb 07 until Feb 10. * (0) efforts making things close to the first published version. * (a) add a lot of keywords * (b) add one integer segement qaul_map * (c) invert() has now one more variable (weights), thank you RCE!. * 16) Feb 17 * (a) add char function to include CVS-based version info. *) modified Apr 27. * 17) Mar 03 * (a) accommodate the choices 8 and 10 of Num_lambda_filter. * 18) Mar 24 and 25 * (a) choice to fetch hmi.V_720s data to give initial vlos_mag. * (b) choice to fetch hmi.M_720s data to give initial field strength. * 19) Apr 1 * (a) Adding new variables, num_lambda_synth and lambda_min_synth * 19')Apr 27 * (a) "hacked" code be (formally) implemented. * Changes are appearing at argument of filt_init_() * Many changes in invert.f90, forward.f90, filter_init.f90, filter_param.f90 as well. * 20) May 16 -- * (0) Delete preprocess-indexes, CHANGFEB and NEWINVRT, because these will be never set non-1. * (a) Add lines to normalize the filter profile. * This feature is controlled with the pre-process var. NRMLFLTR * (b) some lines for version info., COMMENT keyword etc., to include a lot of info. not yet finalized. * (c) Include Yang's confidence index and quality score, being under developement. * To give reference, hmi.M_720s will be always referred, regardless of whether hmi.M will be used as initial guess. * (d) One integer keyword, INVFREEP, is added to show each of 10 free parameters be free or fixed. * Typically, it is 0x000003be or 1110111110. * 21) May 24 --- * (a) HARPATCH, a new choice, is added to host HARP-identified region. * HARPBLOB, another pre-process var., is to choose which blob or rectangle will be processed. * (b) A few thoughts and preparations for hosting CVS version info of Fortran part. not yet finalized .... * (c) clean up and modify comments and rename variables (mostly about DRMS words for input Stokes.) etc. * 22) May 31 * (a) Combined this wrapper with RCE's latest codes. * This associates with changes of argument of void function filt_init_() * 23) June 6 * (a) Add one choice to host multiple HARP maps for one T_REC. * This choice be controlled with MULTHARP. * 24) July 15 -- Oct 13 * (a) Add lines to make HARP box wider, and a few clean-up * (b) A few minor tweaks to process a bit wider box than HARP-defined one * (c) A part calculating filter profile is more flexible and now does not assume the input must be of 4k by 4k. * 25) 2011 Oct 14 * (a) Modified to host RCE's recent efforts * (b) For test data release of AR11158, the checked-in files of this as-of-oct14 version is used. * 26) 2011 Nov 22 until 2012 Jan 13 * (a) Segment name change : series name qual_map is rename to info_map. * * MIND that this change be suspended to be effective. * (b) Add some to MULTHARP-choice to avoid termination when the input HARP segment had been expired or not ready. * (c) Trivials : some language corrections at the standard outputs. * (d) Add comments, to maintain and refresh K.H.'s memory..... * 27) 2012 Jan 23 ... until Feb 3. * (a) To determine and use photon noise level at each pixel, instead of using uniform factor overall pixels, * the third argument of line_init_() be double[4]. * This choice is enabled by setting NLEVPIXL 1. * MIND that line_init_() etc. will be called just before the invert_(), within the pixel-by-pixel loop. * Thus, we need some cares and attention about (de)allocate statements in the Fortran part. * (b) Add one choice, HANDHARP, for using pseudo-HARP defined-by-hand-and-eye. * Note that the current code may have if-statement definining one rectangle, * but plural boxes of interest can be defined by editing the if-condition accordingly. * 28) 2012 Feb 11 -- 21 * (a) Do add a wise, really, way of parallelism suggested by Jesper. * Enable by setting CYCLPRLL preprocess 1. : EQUIAREA must (maybe) be set 1. * (b) Some changes in QUICKRUN so that it will be really useful... * 29) 2012 Mar 27 -- Apr 09 * (a) New VFISV FD10 * 30) 2012 Apr 10 -- 13 * (a) Now assume to use the Fortran codes cleaned-up by RCE, with C-wrapper (this file) modified accordingly. * The Fortrans and C-wrapper modified were provided by RCE, on April 09. * The cleanup by RCE should not affect the outputs, which KH confirmed on Apr 10 * (b) KH includes all changes by RCE, since the last version (29). * (c) Change some name of preprocess parameter turnning on or off the cyclic parallelism * (d) Errors for inclinatin and azimuth are capped at value of 180 degrees. * (e) KH checked in this version to CVS tree on April 13. This version is used for preparing data release (June 1) * 31) 2012 Jun 19 -- * (a) Add a few standard FITS keywords, DATA{VALS,MEAN,RMS} * Add one integer keyword NHARP, number of HARP region: zero for full-disk, 1 or greater for HARP runs. * (b) Add lines to prevent overwriting a full disk data with the HARP one. * Add lines to host option (-f) to enforce overwriting the existing output data record. * (c) This modification should not affect the output data, which KH confirmed. * (d) Checked-in on June ??. * * ------------------------------------------------------------------------------------------------------ */ /* A lot of pre-process switches: Set 0 (turn-off) or 1 (turn-on). * K.H. assumes the value must be 0 or 1. One or a few parameters will accommodate value 2. * If you give other number, consequences will be unpredictable. */ /* A tweak for quick-run for test mode. * MIND that QUICKRUN does not mean this is for QuickLook. * Quick-Look (or nrt) run will be done with the masking data (see MASKPTCH or HARPATCH options, below). * Only some selected columns will be processed, and the selection will be given at if-block(s) somewhere in the code. * Set 1 to turn on this functionality. * Different from another similar choice controlled by RECTANGL, * the output size be same as the input Stokes, typically 4k x 4k, thus no need to modify the .jsd file. * Usually, set 0. */ #define QUICKRUN 0 /* Another tweak for quick-run for test mode. * Do inversion for pixels within a selected rectangle (in CCD coordinate so far) of interest. * Defining the rectangle of interest will be done somewhere in this code. * Because the output array size will be arbitrary, the .jsd file must have "vardim" attribute instead of "variable". * May co-work with QUICKRUN, but KH strongly discourage to use both QUICKRUN and RECTANGL (as of 2012 02 21). */ #define RECTANGL 0 /* Set 1 to normalize filter function BEFORE given to invert() subprogram. * This must be default, since May 16, 2011.*/ #define NRMLFLTR 1 /* Set 1 to save as integer (Rice-compressed) arrays with bscale-increment and bzero-offset. * Otherwise, data be saved in float. * 1 will be default for regular automatic runs. */ #define INTBSCLE 1 /* By setting 1, the initial guess value for vlos_mag is given from hmi.V* series data. * As of 2011 Mar 24, the values are given from hmi.V_720s. * Because hmi.{V,S,M} are made simultaneously at lev. 1 pipeline process, this must always work. * In case hmi.V is not available, initial guess is caluclated from SDO's orbital info. and pixel address. * Note that, inside the VFISV, the initial guess for LoS velocity is replaced with the one * calculated from Stokes I (or V if dark sunspot), thus essentially, this flag may be of less meanings. */ #define VLOSINIT 0 /* Added on March 25, 2011 * By setting 1, the initial guess value for magnetic field strength is given from hmi.M(_720s). * In case hmi.M_720s is not available, the data will be filled with zero value. */ #define MGSTINIT 0 /* Whether or not to determine the noise level at each pixel, or use uniform number over full-disk. * 1 means to do for each pixel. * Added on 2012 Jan 24. * This choice will change where the init_line_() subroutine is called. */ #define NLEVPIXL 1 /* Whether skip or do-anyway when Stokes QUALITY index is not zero. * 1 : do only when the quality index is of ideal condition, 0x000000. * 2 : do only when the index is 0x000000 or 0x000400 * otherwese : fearless-mode, do process regardless of the Stokes quality index value, maybe default, for a while */ #define SKIPBADQ 0 /* By setting 1, the non-NAN, physically meaningful, inside-disk pixels will be evenly assigned to each PE. * Otherwise, the 16M (4k x 4k) pixels will be evenly assinged to PEs. * No side effect found. * Recommend to always keep 1. */ #define EQUIAREA 1 /* Another way to allocate pixels to each PE, suggested by J.S. * In the latest (as of 2012 April) version of VFISV, the elapsed time for processing one pixel will be * significantly pixel-dependent. In this case, EUQIAREA strategy will no longer provide good parallel efficiency. * Set 1 to use this. * CYCLPRLL choice will override EQUIAREA: The value of CYCLPRLL will be first evaluated before EQUAREA will be. * K.H. yet recommends to leave EQUIAREA set 1, regardless of whether CYCLPRLL is turned on or off, for a while. */ #define CYCLPRLL 1 /* By setting 1, the inversion will be processed only for the non-masked pixel. * As of May 24 2011, this choice assumes the masked data is of the same size as the input Stokes. * This choice cannot co-exist with HARPs. * As of Oct. 2011, the HARP module is almost ready, thus, this option will not be used and some day be cleaned up. */ #define MASKPTCH 0 /* Use HARP mask data. * Host each HARP segment map that does not have 4k x 4k size. * If MULTHARP is set to be 1, then output data pixel size will be same as the Stokes (typically 4k x 4k). * If MULTHARP is not set to be 1, then the output data size will be same as each HARP bitmap. * As of May 24, 2011, only one of MASKPTCH and HARPATCH can be 1. * As of May 24, 2011, only one of RECTANGL and HARPATCH can be 1. */ #define HARPATCH 0 /* Which, blob or rectangle of HARP region, will be processed. * 1 for blob. 0 (rectangle) will be default. */ #define HARPBLOB 0 /* Processing multiple HARPs. * If 0, only one HARP explicitly specified by HARPNUM primekey will be processed. * K.H. strongly recommend this parameter be left 1, because the run will fail maybe due to failure of memory (de)allocation, nuts. */ #define MULTHARP 1 /* Added on Jan 27, 2012, by K.H. * This choice will give you an alternative way, simiar to RECTANGL, to process only the (rectangle) region(s) of your interest. * Different from RECTANGL choice, the output will be of 4k x 4k (or same size as the input Stokes). * The output file size of 4k x 4k will bring some conveniences, e.g. for mtracking etc. * Turn on by setting value to be 1. * The size and position of rectangles will be specified at if-then block somewhere in this code. * This choice works only when both HARPATCH and MULTHARP is set 1. */ #define HANDHARP 0 /* Set 1 to enable to fetch the (previous) existing data through JSOC-DRMS as better initial guess. * So for, not used. * Keep this zero for a while being. */ #define TAKEPREV 0 /* Enforce the output T_REC to be the one given at option out2. * The argument for the option out2 must be a string YYYY:MM:DD_hh:mm:ss_TAI, without []. * Good for parameter-tests using the Stokes of the same T_REC, saving outputs at the same series, and using different parameters. */ #define CHNGTREC 0 /* Yang's confidence and quality index definition. * This choice was first added on May 18 2011. */ #define CONFINDX 1 /* Add 4 keywords, defined/reminded on June 19, 2012. * 3 segment-keywords, DATAVALS, DATAMEAN and DATARMS: these will be calculated in set_statistics(). * 1 record-keyword, NHARP (number of HARP regions, 0 for full-disk). * Set 1 to activate this. */ #define ADNEWKWD 1 /* Added on Jun. 21, 2012. * ME will be skipped, when the full-disk data exists at the destination record. * ME will be done, when no record exists, or the existing one is of HARP. * -f option will enforce to do ME, overriding any condition above. * Set 1 to activate this. */ #define CHCKSKIP 1 /* Phil's macro */ #define DIE(msg) {fflush(stdout);fprintf(stderr,"%s, status=%d\n",msg,status); return(status);} /* strings for version info. */ #if HARPATCH == 1 char *module_name = "vfisv FD10 HARP with fixed phase map"; // may be kept unchanged #else char *module_name = "vfisv FD10 with fixed phase map"; // may be kept unchanged #endif /* Version of VFISV. Typically date of last editing (of Fortran or C-wrapper, whichever later). Given by hand....hmmm */ char *version_id = "2013 Mar. 13"; /* external subroutine etc. written in Fortran files, essentially all fortran variables are of pointer */ extern void invert_ (double *, double *, double *, double *, double *, double[*][*], int *, double *); // after Feb 10, 2011 extern void filt_init_ (int *, double *, int *); extern void free_init_ (int *); extern void free_memory_ (); extern void inv_init_ (int *, double *, double *, double *, double *); extern void vfisvalloc_ (int *, int *, int *); extern void lim_init_ (double *); // on and after April 10 2012 #if NLEVPIXL == 1 extern void line_init_ (double *, double *, double [4]); #else extern void line_init_(double *, double *, double *); #endif // extern void svd_init_ (); // commentted out on March 29, 2012 extern void voigt_init_ (); extern void wave_init_ (double *, double *, int *); #include <jsoc_main.h> #include <math.h> #include <mpi.h> ModuleArgs_t module_args[] = { {ARG_STRING, "in", "hmi.S_720s[2012.02.15_00:00:00_TAI]", "input record"}, {ARG_STRING, "out", "hmi.ME_720s", "output series"}, #if CHNGTREC == 1 {ARG_STRING, "out2", "2020.01.02_03:45:00_TAI", "dummy T_REC"}, #endif #if TAKEPREV == 1 {ARG_STRING, "in2", "hmi.ME_720s[2011.02.15_00:00:00_TAI]", "reference inversion results"}, #endif #if HARPATCH == 1 #if MULTHARP == 1 {ARG_STRING, "in3", "hmi.Mharp_720s[][2011.02.15_00:00:00_TAI]", "HARP masking bitmap data"}, // for processing all HARPnum at one instant. #else {ARG_STRING, "in3", "hmi.Mharp_720s[380][2011.02.15_00:00:00_TAI]", "HARP masking bitmap data"}, // for processing a specified HARPnum. : usually not used. #endif #endif #if MASKPTCH == 1 {ARG_STRING, "in3", "su_xudong.mask4inv[2010.08.01_12:12:00_TAI]", "some masking bitmap data"}, // full disk mask data. Stale. To be deleted someday. #endif #if VLOSINIT == 1 {ARG_STRING, "in4", "hmi.V_720s[2012.02.15_00:00:00_TAI]", "Doppler as initial guess"}, #endif #if MGSTINIT == 1 || CONFINDX == 1 {ARG_STRING, "in5", "hmi.M_720s[2012.02.15_00:00:00_TAI]", "magnetogram as initial guess"}, #endif /* default values of inversion options, as of April 2012. */ {ARG_INT, "num_iter", "200", "number of iterations(default: 30)"}, {ARG_INT, "num_lambda", "149", "number of ??(default: 33)"}, {ARG_DOUBLE, "Lambda_Min", "-1998.0", "Intensity threshold (default: -432)"}, {ARG_INT, "Num_lambda_filter", "6", "Number of filters accross the wvl (default: 6)"}, {ARG_INT, "Num_tunning", "6", "Number of ??(default: 6)"}, {ARG_INT, "num_lambda_synth", "49", "Number of synthetic filters (default: 6)"}, {ARG_DOUBLE, "Lambda_Min_synth", "-648.0", "Intensity threshold (default: -432)"}, {ARG_DOUBLE, "svd_tolerance", "1.0e-32", "svd tolerance (default: 1.0e-32)"}, {ARG_DOUBLE, "chi2_stop", "1.0e-15", "chisq-stop (default: 1.0e-6)"}, {ARG_DOUBLE, "Polarization_threshold", "1.0e-2", "polarization threshold (default: 0.01)"}, {ARG_DOUBLE, "Percentage_Jump", "10.0", "Percentage Jump (default: 10%)"}, {ARG_DOUBLE, "Lambda_0", "6173.3433", "Wavelength(default:6173.3433 Angstrom )"}, {ARG_DOUBLE, "Lambda_B", "0.044475775", "FWHM?? (default: 0.044475775)"}, {ARG_DOUBLE, "Delta_Lambda", "27.0", "Delta Lambda(default: 27.0)"}, {ARG_DOUBLE, "Lyotfwhm", "424.0", "Lyot filter FWHM (default: 424.0)"}, {ARG_DOUBLE, "Wnarrow", "172.0", "FSR (full spectral range) of the Narrow-Band Michelson"}, {ARG_DOUBLE, "Wspacing", "69.0", "wavelength spacing between the HMI filters"}, {ARG_DOUBLE, "Intensity_Threshold", "1.0e2", "Intensity threshold (default: 0.8)"}, #if NLEVPIXL == 1 {ARG_DOUBLE, "Noise_LEVELFI", "0.118", "Noise Sigma factor for I"}, {ARG_DOUBLE, "Noise_LEVELFQ", "0.204", "Noise Sigma factor for Q"}, {ARG_DOUBLE, "Noise_LEVELFU", "0.204", "Noise Sigma factor for U"}, {ARG_DOUBLE, "Noise_LEVELFV", "0.204", "Noise Sigma factor for V"}, #else {ARG_DOUBLE, "Noise_LEVEL", "4.9e1", "Intensity threshold (default: 3.0e-3)"}, #endif {ARG_INT, "Continuum", "0", "Intensity threshold (default: 0)"}, /* other options */ {ARG_FLAG, "v", "", "run verbose"}, {ARG_FLAG, "f", "", "enforce overwritng"}, /* trailer */ {} }; int DoIt (void) { /* JSOC-DRMS variables */ CmdParams_t *params = &cmdparams; DRMS_RecordSet_t *inRS; DRMS_Record_t *inRec, *outRec; DRMS_Segment_t *inSeg, *outSeg; DRMS_Array_t *stokes_array, *invrt_array, *err_array, *flg_array, *qmap_array; /* get values at commandline argument : the variables will be treated as constant */ const int NUM_ITERATIONSc = params_get_int(params, "num_iter"); const int NUM_LAMBDAc = params_get_int(params, "num_lambda"); const int NUM_LAMBDA_FILTERc = params_get_int(params, "Num_lambda_filter"); const int NUM_TUNNINGc = params_get_int(params, "Num_tunning"); const int CONTINUUMc = params_get_int(params, "Continuum"); const double SVD_TOLERANCEc = params_get_double(params, "svd_tolerance"); const double CHI2_STOPc = params_get_double(params, "chi2_stop"); const double POLARIZATION_THRESHOLDc = params_get_double(params, "Polarization_threshold"); const double INTENSITY_THRESHOLDc = params_get_double(params, "Intensity_Threshold"); const double PERCENTAGE_JUMPc = params_get_double(params, "Percentage_Jump"); const double LAMBDA_MINc = params_get_double(params, "Lambda_Min"); const double LAMBDA_0c = params_get_double(params, "Lambda_0"); const double LAMBDA_Bc = params_get_double(params, "Lambda_B"); const double DELTA_LAMBDAc = params_get_double(params, "Delta_Lambda"); #if NLEVPIXL == 1 const double NOISE_LEVELFIc = params_get_double(params, "Noise_LEVELFI"); const double NOISE_LEVELFQc = params_get_double(params, "Noise_LEVELFQ"); const double NOISE_LEVELFUc = params_get_double(params, "Noise_LEVELFU"); const double NOISE_LEVELFVc = params_get_double(params, "Noise_LEVELFV"); #else const double NOISE_LEVELc = params_get_double(params, "Noise_LEVEL"); #endif const double LYOTFWHMc = params_get_double(params, "Lyotfwhm"); const double WNARROWc = params_get_double(params, "Wnarrow"); const double WSPACINGc = params_get_double(params, "Wspacing"); const char *indsdescc = params_get_str(params, "in"); const char *outserc = params_get_str(params, "out"); const int NUM_LAMBDA_synthc = params_get_int(params, "num_lambda_synth"); const double LAMBDA_MIN_synthc = params_get_double(params, "Lambda_Min_synth"); #if TAKEPREV == 1 const char *indsdesc2c= params_get_str(params, "in2"); #endif #if MASKPTCH == 1 || HARPATCH == 1 const char *indsdesc3c= params_get_str(params, "in3"); #endif #if VLOSINIT == 1 const char *indsdesc4c= params_get_str(params, "in4"); #endif #if MGSTINIT == 1 || CONFINDX == 1 const char *indsdesc5c= params_get_str(params, "in5"); #endif #if CHNGTREC == 1 const char *outtrecc = params_get_str(params, "out2"); #endif const int verbosec = params_isflagset(params, "v"); const int enfdoitc = params_isflagset(params, "f"); // added on Jun 19, 2012 and later.. /* then copy it to non-constants, to avoid JSOC-compiler's complain */ char *indsdesc, *outser; #if CHNGTREC == 1 char *outtrec; #endif #if TAKEPREV == 1 char *indsdesc2; #endif #if MASKPTCH == 1 || HARPATCH == 1 char *indsdesc3; #endif #if VLOSINIT == 1 char *indsdesc4; #endif #if MGSTINIT == 1 || CONFINDX == 1 char *indsdesc5; #endif int verbose, enfdoit; int NUM_ITERATIONS, NUM_LAMBDA, NUM_LAMBDA_FILTER, NUM_TUNNING, CONTINUUM; double SVD_TOLERANCE, CHI2_STOP, POLARIZATION_THRESHOLD, INTENSITY_THRESHOLD, PERCENTAGE_JUMP; double LAMBDA_0, LAMBDA_B; #if NLEVPIXL == 1 double NOISE_LEVEL[4]; double NOISE_LEVELFI; double NOISE_LEVELFQ; double NOISE_LEVELFU; double NOISE_LEVELFV; #else double NOISE_LEVEL; #endif double LAMBDA_MIN, DELTA_LAMBDA; double LYOTFWHM, WNARROW, WSPACING; int NUM_LAMBDA_synth; double LAMBDA_MIN_synth; NUM_ITERATIONS = NUM_ITERATIONSc; NUM_LAMBDA = NUM_LAMBDAc; NUM_LAMBDA_FILTER = NUM_LAMBDA_FILTERc; NUM_TUNNING = NUM_TUNNINGc; CONTINUUM = CONTINUUMc; SVD_TOLERANCE = SVD_TOLERANCEc; CHI2_STOP = CHI2_STOPc; POLARIZATION_THRESHOLD = POLARIZATION_THRESHOLDc; INTENSITY_THRESHOLD = INTENSITY_THRESHOLDc; PERCENTAGE_JUMP = PERCENTAGE_JUMPc; LAMBDA_0 = LAMBDA_0c; LAMBDA_B = LAMBDA_Bc; #if NLEVPIXL == 1 NOISE_LEVELFI = NOISE_LEVELFIc; NOISE_LEVELFQ = NOISE_LEVELFQc; NOISE_LEVELFU = NOISE_LEVELFUc; NOISE_LEVELFV = NOISE_LEVELFVc; #else NOISE_LEVEL = NOISE_LEVELc; #endif LAMBDA_MIN = LAMBDA_MINc; DELTA_LAMBDA = DELTA_LAMBDAc; LYOTFWHM = LYOTFWHMc; WNARROW = WNARROWc; WSPACING = WSPACINGc; NUM_LAMBDA_synth = NUM_LAMBDA_synthc; LAMBDA_MIN_synth = LAMBDA_MIN_synthc; verbose = verbosec; enfdoit = enfdoitc; indsdesc = strdup(indsdescc); #if CHNGTREC == 1 outtrec= strdup(outtrecc); #endif #if TAKEPREV == 1 indsdesc2= strdup(indsdesc2c); #endif #if MASKPTCH == 1 || HARPATCH == 1 indsdesc3= strdup(indsdesc3c); #endif #if VLOSINIT == 1 indsdesc4= strdup(indsdesc4c); #endif #if MGSTINIT == 1 || CONFINDX == 1 indsdesc5= strdup(indsdesc5c); #endif outser = strdup(outserc); /* important variables for inversions */ int list_free_params[10]={1,1,1,0,1,1,1,1,1,0}; double guess[10]= {15.0,90.0,45.0,0.5,50.0,150.0,0.0,0.4*6e3,0.6*6e3,1.0}; int keyfreep; keyfreep = 0x000003be; /* 1110111110=958=3BE*/ /* inversion-related variables used by wrapper */ char *Resname[] = {"eta_0", "inclination", "azimuth", "damping", "dop_width", "field", "vlos_mag", "src_continuum", "src_grad", "alpha_mag", "field_err","inclination_err","azimuth_err", "vlos_err", "alpha_err", "field_inclination_err","field_az_err","inclin_azimuth_err", "field_alpha_err", "inclination_alpha_err", "azimuth_alpha_err", "chisq", "conv_flag", "qual_map", "confid_map"}; // the last one confid_map is added on May 18. 2011 int Err_ct=12; // MIND newly added convflag and confidence and qualigy index will be treated separately. char segname[16]; char *spname[] = {"I", "Q", "U", "V"}; int spct = (sizeof (spname) / sizeof (char *)); int wlct = NUM_LAMBDA_FILTERc; // now we assume that NUM_LAMBDA_FILTERc is NOT always 6. int paramct = 10; /* bscale and bzero. * bzero_inv[] may be zero. * bscaleinv[] must be in the same order of Resname[]. * Mind that, for some convenience, the order of variables in jsd file may be different from Resname[]. * This does not matter. * In total 25 arrays will be generated by JSOC-VFISV module: 10 physics, 12 error, and 3 supplementals. * Values are mainly based on email from Rebecca on Dec. 9 2010 */ double bzero_inv[25] = {0.0,0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0, 0.0,0.0,0.0, 0.0,0.0,0.0}; double bscaleinv[25] = {0.01,0.01,0.01,0.0001,0.01,0.01, 50.0,0.1,0.1,0.0001, 0.01,0.01,0.01,50.0,0.01, // std. 0.0001,0.0001,0.0001,0.0001, // cor. coef. 0.0001,0.0001,0.0001, // cor. coef. and Chi-sq (on March 29, 2012, Bscale for Chi-sq changed. 1.0,1.0,1.0}; // integer (or character) arrays for convflag, qual_map and confid_map: must be 1.0 /* arrays and variables, used by wrapper */ int *FinalConvFlag; int *FinalConfidMap; int *FinalQualMap; double *FinalRes,*FinalErr; time_t startime, endtime, starttime1, endtime1; double *ddat, *res; double *obs, *scat, *err; double *weights; float *data, *data0; int *nan_map; int rn, rec_ct, sn, seg_ct; int cols, rows, imgpix, imgbytes; int sp, wl, nvar; int j,m,i,k,n; int status; int iquality; int nharp = 0; // zero for full-disk #if RECTANGL == 1 || HARPATCH == 1 /* clipping cropping, address starts (0,0) at the left bottom corner of CCD */ int xleftbot = 1885; int yleftbot = 1410; int xwidth = 100; int yheight = 100; #endif /* MPI variables */ MPI_Status mpistat; int mpi_tag, mpi_rank, mpi_size; int myrank, nprocs, numpix; int istart, iend; int *istartall, *iendall; // start and end pixel addresses, in 16M address space, of a region assigned to each PE. void para_range(int,int,int,int *,int *); // by K.H., written somewhere in this code. #if CYCLPRLL == 1 int *jobassignmap; // job assginment map, in CYCLPRLL choice. ... allocated only at primary (0th) PE. Only Mom knows everything. int jobnum; // number of pixel each PE will take care of in CYCLPRLL choice #endif /* the Sun, SDO, HMI and CCD */ float obs_vr; float crpixx, crpixy; float cdeltx, cdelty; float rsun_ref, dsun_obs; float sunarc; float crota2; float sunradfpix; /* version info., a dummy function to get CVS version info. when checking in.*/ char *meinversion_version(); /*S.C. filter function, written in this code file */ int vfisv_filter(int ,int ,double[*][*],double ,double ,double *,double *,int ,double *,double *,int , double, double [4],double [3],double [4],double [3],double *,double *,double *, int, double ,int ,int ,int ,int); int initialize_vfisv_filter(double *,double *,int *,double *,double *,int *,double *,double *, double *,double *,double *,double *,double *,double *,int *,int *,int *,int *,int *); double filters[NUM_LAMBDA_FILTERc][NUM_LAMBDAc]; double *wavelengthd=NULL; double *frontwindowd=NULL; int nfront; double *wavelengthbd=NULL; double *blockerbd=NULL; int nblocker; double centerblocker; double *phaseNT=NULL; double *phaseT=NULL; double *contrastNT=NULL; double *contrastT=NULL; double *FSR=NULL; double *lineref=NULL; double *wavelengthref=NULL; int referencenlam; double distance; double phaseTi[3]; double phaseNTi[4]; double contrastTi[3]; double contrastNTi[4]; int HCME1; int HCMWB; int HCMNB; int HCMPOL; /* Phil's set_statistics function */ #if ADNEWKWD == 1 int set_statistics(DRMS_Segment_t *, DRMS_Array_t *, int); #endif #if VLOSINIT == 1 float *vlos_init; int iexistdoppler; iexistdoppler = 0; // default, no-existing.. #endif #if MGSTINIT == 1 || CONFINDX == 1 float *mgst_init; int iexistmagnetogram; iexistmagnetogram = 0; // default, no-existing.. float *blosgram; #endif #if TAKEPREV == 1 float *prevdata; int iexistprev; #endif #if MASKPTCH == 1 || HARPATCH == 1 int *patchmask; int iexistpatchmask; iexistpatchmask = 0; // default, no-existing.. #endif /* check of preprocess parameters : MIND that these do not cover all possible prohibited choices. */ #if MASKPTCH == 1 && HARPATCH == 1 DIE(" Both MASKPTCH and HARPATCH set 1. So terminated !\n"); #endif #if RECTANGL == 1 && HARPATCH == 1 DIE(" Both RECTANGL and HARPATCH set 1. So terminated !\n"); #endif #if EQUIAREA != 1 && CYCLPRLL == 1 DIE(" CYCLPRLL cannot work when EQUIAREA is turned off. So terminated !\n"); #endif /* time at the start */ time(&startime); /* Initalizing MPI, each PE finds where it is, and how many CPUs or cores be used. */ MPI_Status mpi_stat; status = 0; MPI_Init (&status, NULL); MPI_Comm_rank (MPI_COMM_WORLD, &mpi_rank); MPI_Comm_size (MPI_COMM_WORLD, &mpi_size); istartall = (int *)malloc(sizeof(int) * mpi_size); iendall = (int *)malloc(sizeof(int) * mpi_size); MPI_Barrier(MPI_COMM_WORLD); if (mpi_rank == 0){printf ("%s Ver. %s\n", module_name, version_id);} #if CHCKSKIP == 1 /* first of all, check if the output data already exists or not, then decide to do ME VFISV or quit */ { // scope limiter int idoit; idoit = 0; // 1 for to-do, otherwise for skip if (enfdoit) { if (mpi_rank == 0){printf ("Enforcing running VFISV even when the output destination record exits.\n");} idoit = 1; } else { if (mpi_rank == 0) { /* try to provisionally open the input Stokes record */ inRS = drms_open_records (drms_env, indsdesc, &status); /* open input record_set */ if (status) {DIE("drms_open_records failed.\n");} if ((rec_ct = inRS->n) == 0){DIE("No records in selected dataset.\n");} if ((rec_ct = inRS->n) > 1){fprintf (stderr, "Warning: only first record in selected set processed\n");} inRec = inRS->records[0]; // This wrapper assume only the first Stokes be taken care of. // inSeg = drms_segment_lookupnum (inRec, 0); TIME t_rec = drms_getkey_time(inRec,"T_REC",&status); drms_close_records(inRS, DRMS_FREE_RECORD); // once close the input Stokes record. /* try to open the destination record */ DRMS_RecordSet_t *inRS2; DRMS_Record_t *inRec2; char timestr2[26]; sprint_time(timestr2,t_rec,"TAI",0); char stroutdat[80]; sprintf(stroutdat,"%s[%s]",outserc,timestr2); printf(" destination record : %s ",stroutdat); char *inQuery2 = stroutdat; inRS2 = drms_open_records(drms_env, inQuery2, &status); if (status || inRS2->n == 0) { printf("not exist, so ME will start.\n"); idoit = 1; } else { printf(" exist.:"); idoit = 0; inRec2= inRS2->records[0]; // there must be only one record, this case. int nprc2; nprc2 = drms_getkey_float(inRec2,"INVNPRCS",&status); if (nprc2 < 1e7) { idoit = 1; printf(" but it seems to be of HARP, so ME VFISV will start.\n"); } else { idoit = 0; printf(" the existing one seems to be of full-disk, so ME VFISV will be skipped.\n"); } } drms_close_records(inRS2, DRMS_FREE_RECORD); } // end if mpi_rank is 0 MPI_Barrier(MPI_COMM_WORLD); int *ibuff; ibuff=(int *)malloc(sizeof(int)*1); ibuff[0]=idoit; MPI_Bcast(ibuff,1,MPI_INT,0,MPI_COMM_WORLD); idoit = ibuff[0]; // unpacking free(ibuff); } // endif enforce do-it option is given or not. if (idoit != 1) { if (mpi_rank == 0){printf("ME VFISV run will be skipped. Good bye !\n");} MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); return 0; } } // scope limiter #endif /* end if CHCKSKIP is 1 */ /* very very long long if-block lines for the primary PE. * Reading data, allocating memory, assigning job amount and sending the input data to the other PEs. */ if (mpi_rank == 0) { // printf ("%s Ver. %s\n", module_name, version_id); if (verbose) printf ("%d CPU/core(s) be used for parallel-inversion. \n", mpi_size); // printf("Lambda_O= %f\n",LAMBDA_0); #if MASKPTCH == 1 { /* limit scope for some DRMS variables */ char segname[100]; /* arbitrary long string... */ char *inData; /* I-O pointer */ DRMS_Array_t *inArray; /* add some DRMS variables within this scope */ DRMS_Segment_t *inSeg; DRMS_Record_t *inRec; DRMS_RecordSet_t *inRS; int nnx, nny; if (verbose) printf(" now loading mask-data : %s\n",indsdesc3); inRS = drms_open_records (drms_env, indsdesc3, &status); /* open input record_set */ /* this case, never say die.... just turn on flag */ if ((status) || ((rec_ct = inRS->n) == 0)) { iexistpatchmask = 0; printf(" skip, no data series : %s\n",indsdesc3); } else { iexistpatchmask = 1; if ((rec_ct = inRS->n) > 1){fprintf (stderr, "Warning: only first record in selected set processed\n");} rn = 0; inRec = inRS->records[rn]; char *Resname[] = {"mask"}; sprintf(segname,"%s",Resname[0]); inSeg = drms_segment_lookup(inRec,segname); cols = inSeg->axis[0]; rows = inSeg->axis[1]; imgpix = cols * rows; patchmask = (int *)malloc (sizeof (int) * imgpix * 1); int iseg; for (iseg = 0; iseg < 1; iseg++) // maybe just one segment... { sprintf(segname,"%s",Resname[iseg]); if (verbose) printf(" now loading segment : %-20s",segname); inSeg = drms_segment_lookup(inRec,segname); inArray= drms_segment_read(inSeg, DRMS_TYPE_CHAR, &status); if (status) DIE("Cant read segment!\n"); inData =(char *)inArray->data; nnx = inArray->axis[0]; // may be same as cols nny = inArray->axis[1]; // may be same as rows if (verbose) {printf(" Nx Ny are = %d %d\n", nnx, nny);} for (n = 0; n < nnx * nny; n++){patchmask[n+iseg*imgpix]=inData[n];} // silly but safe way to pass data drms_free_array(inArray); // without this, well, things go mad. } drms_close_records (inRS, DRMS_FREE_RECORD); /* close record */ } } /* end of scope for some DRMS variables */ #endif /* end if MASKPTCH is 1 */ /* If input Mask map (by HARP or else) does not have pixel size of 4k x 4k, * some variable must be modified. * Here four variables, xleftbot, yleftbot, xwidth and ywidth, * will be modified in accordance with the keywords info. of HARP data */ #if HARPATCH == 1 && MULTHARP != 1 { /* limit scope for some DRMS variables */ char segname[100]; /* arbitrary long string... */ char *inData; /* I-O pointer */ DRMS_Array_t *inArray; /* add some DRMS variables within this scope */ DRMS_Segment_t *inSeg; DRMS_Record_t *inRec; DRMS_RecordSet_t *inRS; int nnx, nny; int colsL, rowsL, imgpixL; // MIND that the HARP will not be of 4k x 4k. if (verbose) printf(" now loading HARP-data : %s\n",indsdesc3); inRS = drms_open_records (drms_env, indsdesc3, &status); /* open input record_set */ /* this case, never say die.... just turn on flag */ if ((status) || ((rec_ct = inRS->n) == 0)) { iexistpatchmask = 0; printf(" skip, no data series : %s\n",indsdesc3); } else { iexistpatchmask = 1; if ((rec_ct = inRS->n) > 1){fprintf (stderr, "Warning: only first record in selected set processed\n");} rn = 0; inRec = inRS->records[rn]; /* if no data file actually exist for unknown reasons ........... abort */ iquality = drms_getkey_int(inRec,"QUALITY",&status); if (iquality < 0){DIE("No HARP file exist on disk, process terminated.\n");} char *Resname[] = {"bitmap"}; sprintf(segname,"%s",Resname[0]); inSeg = drms_segment_lookup(inRec,segname); colsL = inSeg->axis[0]; // we need Naxis(1,2) rowsL = inSeg->axis[1]; imgpixL = colsL * rowsL; patchmask = (int *)malloc (sizeof (int) * imgpixL * 1); int iseg; for (iseg = 0; iseg < 1; iseg++) // maybe just one segment... { sprintf(segname,"%s",Resname[iseg]); if (verbose) printf(" now loading segment : %-20s",segname); inSeg = drms_segment_lookup(inRec,segname); inArray= drms_segment_read(inSeg, DRMS_TYPE_CHAR, &status); if (status) DIE("Cant read segment!\n"); inData =(char *)inArray->data; nnx = inArray->axis[0]; // may be same as colsL nny = inArray->axis[1]; // may be same as rowsL if (verbose) {printf(" Nx Ny are = %d %d\n", nnx, nny);} for (n = 0; n < nnx * nny; n++){patchmask[n+iseg*imgpixL]=inData[n];} // silly but safe way to pass data drms_free_array(inArray); // without this, well, things go mad. } xleftbot = drms_getkey_int(inRec,"CRPIX1",&status); yleftbot = drms_getkey_int(inRec,"CRPIX2",&status); xwidth = colsL; yheight = rowsL; if (verbose) {printf(" HARP info. xleftbot yleftbot xwidth yheight = %d %d %d %d\n",xleftbot,yleftbot,xwidth,yheight);} xleftbot = xleftbot - 1; yleftbot = yleftbot - 1; if (verbose) {printf(" HARP xleftbot yleftbot were shifted = %d %d\n",xleftbot,yleftbot);} drms_close_records (inRS, DRMS_FREE_RECORD); /* close record */ } } /* end of scope for some DRMS variables */ #endif /* end if HARPATCH is 1 and MULTHARP is NOT 1 */ #if TAKEPREV == 1 { /* limit scope for some DRMS variables */ char segname[100]; /* arbitrary long string... */ float *inData; /* I-O pointer */ DRMS_Array_t *inArray; /* add some DRMS variables within this scope */ DRMS_Segment_t *inSeg; DRMS_Record_t *inRec; DRMS_RecordSet_t *inRS; int nnx, nny; if (verbose) printf(" now loading previous results series : %s\n",indsdesc2); inRS = drms_open_records (drms_env, indsdesc2, &status); /* open input record_set */ // if (status) {DIE("drms_open_records failed.\n");} // if ((rec_ct = inRS->n) == 0){DIE("No records in selected dataset.\n");} /* this case, never say die.... just turn on flag */ if ((status) || ((rec_ct = inRS->n) == 0)) { iexistprev=0; if (verbose) printf(" skip, no data series : %s\n",indsdesc2); } else { iexistprev=1; if ((rec_ct = inRS->n) > 1){fprintf (stderr, "Warning: only first record in selected set processed\n");} rn = 0; inRec = inRS->records[rn]; inSeg = drms_segment_lookupnum (inRec, 0); cols = inSeg->axis[0]; rows = inSeg->axis[1]; imgpix = cols * rows; prevdata = (float *)malloc (sizeof (float) * imgpix * (paramct+Err_ct)); int iseg; for (iseg = 0; iseg < (paramct+Err_ct); iseg++) // here we take both physics data and error arrays. { sprintf(segname,"%s",Resname[iseg]); if (verbose) printf(" now loading segment of previous results : %-20s",segname); inSeg = drms_segment_lookup(inRec,segname); inArray= drms_segment_read(inSeg, DRMS_TYPE_FLOAT, &status); if (status) DIE("Cant read segment!\n"); inData =(float *)inArray->data; nnx = inArray->axis[0]; // may be same as cols nny = inArray->axis[1]; // may be same as rows if (verbose) {printf(" Nx Ny are = %d %d\n", nnx, nny);} for (n = 0; n < nnx * nny; n++){prevdata[n+iseg*imgpix]=inData[n];} // silly but safe way to pass data drms_free_array(inArray); // without this, well, things go mad. } drms_close_records (inRS, DRMS_FREE_RECORD); /* close record */ } } /* end of scope for some DRMS variables */ #endif /* endif TAKEPREV is 1 or not */ /* Getting Stokes */ inRS = drms_open_records (drms_env, indsdesc, &status); /* open input record_set */ if (status) {DIE("drms_open_records failed.\n");} if ((rec_ct = inRS->n) == 0){DIE("No records in selected dataset.\n");} if ((rec_ct = inRS->n) > 1){fprintf (stderr, "Warning: only first record in selected set processed\n");} rn = 0; // inversion code will handle only the first record. inRec = inRS->records[rn]; /* if no data file actually exist for unknown reasons ........... abort */ iquality = drms_getkey_int(inRec,"QUALITY",&status); if (iquality < 0){DIE("No Stokes file exist on disk, process terminated.\n");} inSeg = drms_segment_lookupnum (inRec, 0); cols = inSeg->axis[0]; rows = inSeg->axis[1]; imgpix = cols * rows; imgbytes = imgpix * sizeof (float); nvar = wlct * spct; #if TAKEPREV == 1 if (iexistprev==0){prevdata = (float *)malloc (sizeof (float) * imgpix * (paramct+Err_ct));} /* allocate anyway */ #endif data = data0 = (float *)malloc (sizeof (float) * imgpix * nvar); // a noble use of pointer, by Priya & Rick nan_map=(int *)calloc(imgpix, sizeof (int)); // printf("now loading Stokes of %d wavelength \n",wlct); for (sp = 0; sp < spct; sp++) /* spct=4, wlct maybe 6 (or 8 or 10) */ { for (wl = 0; wl < wlct; wl++) { /* * By K.H. * Since 2011 March 7, we assume the wlct can be 6, 8 or 10. * The segname will be modified so that the order will be matching with the one * in the hmi.S2_720s (or else S.C. prepared for non-6 test). */ if (NUM_LAMBDA_FILTER == 6) { sprintf (segname, "%s%d", spname[sp], wl); // same as before March 07, 2011 } if (NUM_LAMBDA_FILTER == 8) // for 8-wavelength filter, inv. order of 6, I5, I4, I3, I2, I1, I0, and I7 { int idummy; if (wl == 0){idummy = 7;}else{idummy = wl - 1;} sprintf (segname, "%s%d",spname[sp],idummy); } if (NUM_LAMBDA_FILTER == 10) // for 10, inv order of I8, I6, I5, I4, I3, I2, I1, I0, I7, and I9. { int idummy; idummy = wl - 2; if (wl == 0){idummy = 9;} if (wl == 1){idummy = 7;} if (wl == 9){idummy = 8;} sprintf (segname, "%s%d",spname[sp],idummy); } if (verbose){printf("now loading Stokes : %s\n",segname);} if ((inSeg = drms_segment_lookup (inRec, segname)) == NULL){ fprintf (stderr, "Error reading segment %s of record %d\n", segname, rn); return 1; } /* 4 x {6, 8 or 10} segments, 4k x 4k data points each */ stokes_array = drms_segment_read (inSeg, DRMS_TYPE_FLOAT, &status); if (status) {DIE("Cant read Stokes data !\n");} memcpy (data, stokes_array->data, imgbytes); drms_free_array (stokes_array); data += imgpix; // another noble use of pointer, by Priya & Rick } } data = data0; printf("Imgpix= %d\n",imgpix); /* get quality index at keyword field of Stokes */ iquality = drms_getkey_int(inRec,"QUALITY",&status); // quality index, nice data must have zero-value. #if SKIPBADQ == 1 { char trectmp2[26]; TIME trectmp1 = drms_getkey_time(inRec,"T_REC",&status); sprint_time(trectmp2,trectmp1,"TAI",0); printf("QUALITY index at [%s] is %08x\n",trectmp2,iquality); if (iquality !=0){DIE(" QUALITY index is not zero, so process terminated !");} } #endif #if SKIPBADQ == 2 { char trectmp2[26]; TIME trectmp1 = drms_getkey_time(inRec,"T_REC",&status); sprint_time(trectmp2,trectmp1,"TAI",0); printf("QUALITY index at [%s] is %08x\n",trectmp2,iquality); if ((iquality !=0) && (iquality !=0x00000400)){DIE(" QUALITY index does not satisfy criteria, so process terminated !");} } #endif obs_vr = drms_getkey_float(inRec,"OBS_VR",&status); // SDO's relative motion toward/away from the Sun. obs_vr = obs_vr * 100.0; // in cm per sec crota2 = drms_getkey_float(inRec,"CROTA2",&status); // P-angle... right? crpixx = drms_getkey_float(inRec,"CRPIX1",&status); // center of the solar disk crpixy = drms_getkey_float(inRec,"CRPIX2",&status); cdeltx = drms_getkey_float(inRec,"CDELT1",&status); // arcsec per pixel cdelty = drms_getkey_float(inRec,"CDELT2",&status); rsun_ref = drms_getkey_float(inRec,"RSUN_REF",&status); // solar radius in meter dsun_obs = drms_getkey_float(inRec,"DSUN_OBS",&status); // distance from Sun to SDO in meter sunarc = asin(rsun_ref/dsun_obs) // arc-sin in radian / 3.14159265358979e0 * 180.0 * 3600.0; // radian to arc-second printf("solar radius is %f in arcsec \n",sunarc); sunradfpix = sunarc / (cdeltx + cdelty) * 2.0; // just averaging for simplicity. printf("solar radius is %f in CCD pix.\n",sunradfpix); if ((isnan(sunarc)) ||((isnan(crpixx)) || isnan(crpixy))) // in case something had gone wrong. { sunarc = (float)(cols+rows) * 0.5; crpixx = (float)cols * 0.5 + 0.5; crpixy = (float)rows * 0.5 + 0.5; } /* 2011 June 6 * Here mask map has pixel size of 4k x 4k to host multi-HARP maps, * The four variables, xleftbot, yleftbot, xwidth and ywidth be given 0, 0, 4096 and 4096. */ #if HARPATCH == 1 && MULTHARP == 1 patchmask = (int *)malloc (sizeof (int) * imgpix); /* allocate same size as Stokes */ { /* limit scope for some DRMS variables */ int i; for (i = 0; i < imgpix; i++){patchmask[i]=0;} // 0 means .. skip! char segname[100]; /* arbitrary long string... */ char *inData; /* I-O pointer */ DRMS_Array_t *inArray; /* add some DRMS variables within this scope */ DRMS_Segment_t *inSeg; DRMS_Record_t *inRec; DRMS_RecordSet_t *inRS; int nnx, nny; int colsL, rowsL, imgpixL; // MIND that the HARP will not be of 4k x 4k. #if HANDHARP != 1 /* do with real-HARP data */ if (verbose) printf(" now loading HARP-data : %s\n",indsdesc3); inRS = drms_open_records (drms_env, indsdesc3, &status); /* open input record_set */ /* this case, say die .... just turn on flag */ if ((status) || ((rec_ct = inRS->n) == 0)) { iexistpatchmask = 0; // printf(" skip, no data series : %s\n",indsdesc3); DIE("terminated due to no HARP data.\n"); } else { rec_ct = inRS->n; // redo .. just in case. nharp = rec_ct; // for keyword NHARP printf(" There are %d HARP for %s\n",rec_ct, indsdesc3); iexistpatchmask = 1; for (rn = 0; rn < rec_ct; rn++) { inRec = inRS->records[rn]; /* if no data file actually exist for unknown reasons ........... abort */ iquality = drms_getkey_int(inRec,"QUALITY",&status); if (iquality < 0){DIE("No HARP file exist on disk, process terminated.\n");} char *Resname[] = {"bitmap"}; sprintf(segname,"%s",Resname[0]); inSeg = drms_segment_lookup(inRec,segname); colsL = inSeg->axis[0]; // we need the Naxis(1,2) rowsL = inSeg->axis[1]; imgpixL = colsL * rowsL; int *patchmaskL; patchmaskL = (int *)malloc (sizeof (int) * imgpixL * 1); int iseg; for (iseg = 0; iseg < 1; iseg++) // maybe just one segment... { sprintf(segname,"%s",Resname[iseg]); if (verbose) printf(" now loading segment : %-20s",segname); inSeg = drms_segment_lookup(inRec,segname); inArray= drms_segment_read(inSeg, DRMS_TYPE_CHAR, &status); // if (status) DIE("Cant read segment!\n"); // never say die this case. if (status) { printf("no valid HARP data, maybe expired ... skip %d th HARP\n", iseg); } else { inData =(char *)inArray->data; nnx = inArray->axis[0]; // may be same as colsL nny = inArray->axis[1]; // may be same as rowsL if (verbose) {printf(" Nx Ny are = %d %d\n", nnx, nny);} for (n = 0; n < nnx * nny; n++){patchmaskL[n+iseg*imgpixL]=inData[n];} // silly but safe way to pass data } drms_free_array(inArray); // without this, well, things go mad. } // end-for loop for bit map segment. int xleftbotL, yleftbotL; xleftbotL = drms_getkey_int(inRec,"CRPIX1",&status); yleftbotL = drms_getkey_int(inRec,"CRPIX2",&status); xwidth = colsL; yheight = rowsL; if (verbose) {printf(" HARP info. xleftbot yleftbot xwidth yheight = %d %d %d %d\n",xleftbotL,yleftbotL,xwidth,yheight);} #if 0 /* do only specified HARP region(s) */ int numharp = drms_getkey_time(inRec,"HARPNUM",&status); if ((numharp == 2081) || (numharp == 4087)) // give HARP numbers here as many as you want. { #if 1 /* enfoce the size to 700 or greater */ int icenter, jcenter; icenter = xleftbotL + colsL / 2; jcenter = yleftbotL + rowsL / 2; if (colsL < 700){xleftbotL = icenter - 350; colsL = 700;} if (rowsL < 700){yleftbotL = jcenter - 350; rowsL = 700;} #endif int i2, j2, n2, m2; for (i2 = 0; i2 < colsL; i2++) { for (j2 = 0; j2 < rowsL; j2++) { int iL, jL; jL = j2 + yleftbotL - 1; iL = i2 + xleftbotL - 1; if (iL < 0){iL = 0;} if (iL > cols - 1){iL = cols-1;} if (jL < 0){jL = 0;} if (jL > rows - 1){jL = rows-1;} m2 = jL * cols + iL; patchmask[m2] = 600; // here assume non-blob ... some larger number than 4. } } } else { printf(" Out of interest this time, thus skipped : RecNum and HARPnum = %d %d\n",rn,numharp); } #else /* a standard use of HARP : do all */ #if 1 /* extend HARP box with some prefixed margin */ int iextendx = 50; int iextendy = 50; xleftbotL = xleftbotL - iextendx; yleftbotL = yleftbotL - iextendy; colsL = colsL + iextendx * 2; rowsL = rowsL + iextendy * 2; #endif #if 0 /* extend HARP box; force to be 700 pixel or bigger */ { int icenter, jcenter; icenter = xleftbotL + colsL / 2; jcenter = yleftbotL + rowsL / 2; if (colsL < 700){xleftbotL = icenter - 350; colsL = 700;} if (rowsL < 700){yleftbotL = jcenter - 350; rowsL = 700;} } #endif int i2, j2, m2; for (i2 = 0; i2 < colsL; i2++) { for (j2 = 0; j2 < rowsL; j2++) { int iL, jL; jL = j2 + yleftbotL - 1; iL = i2 + xleftbotL - 1; if (iL < 0){iL = 0;} if (iL > cols - 1){iL = cols-1;} if (jL < 0){jL = 0;} if (jL > rows - 1){jL = rows-1;} m2 = jL * cols + iL; patchmask[m2] = 600; // here assume non-blob ... some larger number than 4. } } #endif // endif whether the standard use of HAPR or something else. free(patchmaskL); } // end-for loop for each HARP number at a specified time drms_close_records (inRS, DRMS_FREE_RECORD); /* close record */ } // end-if the HARP record(s) exist or not. #else /* pseudo-HARP, by hand */ iexistpatchmask = 1; // pretend to have read the authentic HARP data. int xleftbotL, yleftbotL; xleftbotL = 1450; // x of left bottom corner yleftbotL = 1250; // y of left bottom corner colsL = 600; // width rowsL = 400; // height xwidth = colsL; yheight = rowsL; if (verbose) {printf(" pseudo-HARP info. xleftbot yleftbot xwidth yheight = %d %d %d %d\n",xleftbotL,yleftbotL,xwidth,yheight);} int i2, j2, m2; for (i2 = 0; i2 < colsL; i2++) { for (j2 = 0; j2 < rowsL; j2++) { int iL, jL; jL = j2 + yleftbotL - 1; iL = i2 + xleftbotL - 1; if (iL < 0){iL = 0;} if (iL > cols - 1){iL = cols-1;} if (jL < 0){jL = 0;} if (jL > rows - 1){jL = rows-1;} m2 = jL * cols + iL; patchmask[m2] = 600; // here assume non-blob ... some larger number than 4. } } #endif /* end if HANDHARP is NOT 1 or is 1 */ /* recover some info. */ xwidth = cols; // must be same as Stokes yheight = rows; xleftbot = 0; yleftbot = 0; } /* end of scope for some DRMS variables */ #endif /* end if HARPATCH is 1 and MULTHARP is 1 */ #if MASKPTCH == 1 || HARPATCH == 1 if (iexistpatchmask==0){patchmask = (int *)malloc (sizeof (int) * imgpix);} /* allocate anyway */ #endif /* 2011 March 24, added by K.H. to try to get hmi.V_720s as initial guess */ #if VLOSINIT == 1 float defvlosinit; defvlosinit = guess[6]; { /* limit scope for some DRMS variables */ char segname[100]; /* arbitrary long string... */ float *inData; /* I-O pointer */ DRMS_Array_t *inArray; /* add some DRMS variables within this scope */ DRMS_Segment_t *inSeg; DRMS_Record_t *inRec; DRMS_RecordSet_t *inRS; int nnx, nny; if (verbose) printf(" now loading Doppler : %s\n",indsdesc4); inRS = drms_open_records (drms_env, indsdesc4, &status); /* open input record_set */ /* this case, never say die.... just turn on flag */ if ((status) || ((rec_ct = inRS->n) == 0)) { iexistdoppler = 0; printf(" no data series : %s\n",indsdesc4); } else { iexistdoppler = 1; if ((rec_ct = inRS->n) > 1){fprintf (stderr, "Warning: only first record in selected set processed\n");} rn = 0; inRec = inRS->records[rn]; /* if no data file actually exist for unknown reasons ........... abort */ iquality = drms_getkey_int(inRec,"QUALITY",&status); if (iquality < 0){DIE("No Doppler file exist on disk, process terminated.\n");} char *Resname[] = {"Dopplergram"}; sprintf(segname,"%s",Resname[0]); inSeg = drms_segment_lookup(inRec,segname); cols = inSeg->axis[0]; rows = inSeg->axis[1]; imgpix = cols * rows; vlos_init = (float *)malloc (sizeof(float) * imgpix); int iseg; for (iseg = 0; iseg < 1; iseg++) // maybe just one segment... { sprintf(segname,"%s",Resname[iseg]); if (verbose) printf(" now loading segment : %-20s",segname); inSeg = drms_segment_lookup(inRec,segname); inArray= drms_segment_read(inSeg, DRMS_TYPE_FLOAT, &status); if (status) DIE("Cant read Dopplergram data !\n"); inData =(float *)inArray->data; nnx = inArray->axis[0]; // may be same as cols nny = inArray->axis[1]; // may be same as rows if (verbose) {printf(" Nx Ny are = %d %d\n", nnx, nny);} for (n = 0; n < nnx * nny; n++){vlos_init[n]=inData[n]*100.0;} // silly but safe way to pass data, m/s to cm/s drms_free_array(inArray); // without this, things go mad. } drms_close_records (inRS, DRMS_FREE_RECORD); /* close record */ } } /* end of scope for some DRMS variables */ /* If hmi.V exisits, do some minor modification. * In case the apparent solar disk sizes in V and S are different (least likely). * At the outermost pixels of the disk */ if (iexistdoppler == 1) { for (n = 0; n < imgpix; n++) { float fpixdist, fxpix, fypix; int ix, iy; ix = n % cols; iy = n / cols; fxpix = ((float)(ix) -(crpixx - 1.0)) * cdeltx; // in arc-sec fypix = ((float)(iy) -(crpixy - 1.0)) * cdelty; fpixdist = fxpix * fxpix + fypix * fypix + 1e-20; fpixdist = sqrt(fpixdist); if (fpixdist > sunarc * 0.99) { vlos_init[n] = defvlosinit; } } } /* making Vlos_init if no V was available (least likely, just in case) */ if (iexistdoppler == 0) { vlos_init = (float *)malloc (sizeof (float) * imgpix * 1); /* allocate anyway */ float cospangle, pangrad; pangrad = crota2 / 180.0 * 3.14159265358979; cospangle = cos(pangrad); for (n = 0; n < imgpix; n++) { float fpixdist, fxpix, fypix; int ix, iy; ix = n % cols; iy = n / cols; fxpix = ((float)(ix) -(crpixx - 1.0)) * cdeltx; // in arc-sec fypix = ((float)(iy) -(crpixy - 1.0)) * cdelty; fpixdist = fxpix * fxpix + fypix * fypix + 1e-20; fpixdist = sqrt(fpixdist); if (fpixdist < sunarc * 0.99) { float sinphi, sintheta, costheta; sintheta = fypix/sunarc; // B0.. ? so what !? costheta = 1.0 - sintheta*sintheta; if (costheta > 0.0){costheta = sqrt(costheta);}else{costheta = 0.0;} float omega, vlosoldiff; omega = 14.713 - 2.396 * sintheta * sintheta - 1.787 * sintheta * sintheta * sintheta * sintheta; omega = omega / (24.0 * 3600.0) * 3.14159265358979 / 180.0 ; // in radian per second vlosoldiff = rsun_ref * 100.0 * omega; // rsun_ref is in m per sec float fwork; sinphi = fxpix/ (costheta * sunarc); fwork = sinphi * cospangle; vlosoldiff = vlosoldiff * fwork; vlos_init[n] = -obs_vr + vlosoldiff; // check sign etc..... } else { vlos_init[n] = defvlosinit; // replace with the default given by RCE. } } } #endif // endif VLOSINIT is 1 /* 2011 March 25, and May 17, added by K.H. to try to get hmi.M_720s as initial guess or as reference for bad-pixel judgement */ #if MGSTINIT == 1 || CONFINDX == 1 float defmgstinit; defmgstinit = guess[5]; { /* limit scope for some DRMS variables */ char segname[100]; /* arbitrary long string... */ float *inData; /* I-O pointer */ DRMS_Array_t *inArray; DRMS_Segment_t *inSeg; DRMS_Record_t *inRec; DRMS_RecordSet_t *inRS; int nnx, nny; if (verbose) printf(" now loading magnetogram : %s\n",indsdesc5); inRS = drms_open_records (drms_env, indsdesc5, &status); /* open input record_set */ /* this case, never say die.... just turn on flag */ if ((status) || ((rec_ct = inRS->n) == 0)) { iexistmagnetogram = 0; printf(" no data series : %s\n",indsdesc5); } else { iexistmagnetogram = 1; if ((rec_ct = inRS->n) > 1){fprintf (stderr, "Warning: only first record in selected set processed\n");} rn = 0; inRec = inRS->records[rn]; /* if no data file actually exist for unknown reasons ........... abort */ iquality = drms_getkey_int(inRec,"QUALITY",&status); if (iquality < 0){DIE("No Magnetogram file exist on disk, process terminated.\n");} char *Resname[] = {"magnetogram"}; sprintf(segname,"%s",Resname[0]); inSeg = drms_segment_lookup(inRec,segname); cols = inSeg->axis[0]; rows = inSeg->axis[1]; imgpix = cols * rows; mgst_init = (float *)malloc (sizeof(float) * imgpix); blosgram = (float *)malloc (sizeof(float) * imgpix); int iseg; for (iseg = 0; iseg < 1; iseg++) // maybe just one segment... { sprintf(segname,"%s",Resname[iseg]); if (verbose) printf(" now loading segment : %-20s",segname); inSeg = drms_segment_lookup(inRec,segname); inArray= drms_segment_read(inSeg, DRMS_TYPE_FLOAT, &status); if (status) DIE("Cant read Magnetogram data !\n"); inData =(float *)inArray->data; nnx = inArray->axis[0]; // must be same as cols nny = inArray->axis[1]; // must be same as rows if (verbose) {printf(" Nx Ny are = %d %d\n", nnx, nny);} for (n = 0; n < nnx * nny; n++){blosgram[n]=inData[n];} // here both in gauss. drms_free_array(inArray); // without this, things go mad. } drms_close_records (inRS, DRMS_FREE_RECORD); /* close record */ } } /* end of scope for some DRMS variables */ /* convert from Blos to Bstrength, with some tweaks */ if (iexistmagnetogram == 1) { for (n = 0; n < imgpix; n++) { float fpixdist, fxpix, fypix; int ix, iy; ix = n % cols; iy = n / cols; fxpix = ((float)(ix) -(crpixx - 1.0)) * cdeltx; // in arc-sec fypix = ((float)(iy) -(crpixy - 1.0)) * cdelty; fpixdist = fxpix * fxpix + fypix * fypix + 1e-20; fpixdist = sqrt(fpixdist); if (fpixdist > sunarc * 0.99) { mgst_init[n] = defmgstinit; // replace with the default given by RCE. } else { float cosmu, ftmp; cosmu = 1.0e0 - fpixdist*fpixdist/(sunarc*sunarc); ftmp = fabs(blosgram[n]) / (0.8 * sqrt(cosmu) + 0.2); // KH presume this conversion came from Phil's work. if (ftmp > 4.0e3){ftmp = 4.0e3;} if (ftmp < -4.0e3){ftmp = -4.0e3;} mgst_init[n] = ftmp; } } } /* making mgst_init anyway if no M data was available */ if (iexistmagnetogram == 0) { mgst_init = (float *)malloc (sizeof (float) * imgpix * 1); /* allocate anyway */ blosgram = (float *)malloc (sizeof (float) * imgpix * 1); /* allocate anyway */ for (n = 0; n < imgpix; n++){mgst_init[n]=0.0;} } #endif // endif MGSTINIT or CONFINDX is 1 /* Map of invalid values (NaN or all-zero) , or off-disk, out of rectangle of interest, or out of the HARP region etc. */ for (n = 0; n < imgpix; n++) { nan_map[n] = 0; // because nan_map was calloc-ed, this is not needed. double sumsqr; // better be of double precision, maybe... sumsqr = 0.0; for (m = 0; m < nvar; m++){sumsqr = sumsqr + data[n + m*imgpix] * data[n + m*imgpix];} if (sumsqr < 1.0e-2){nan_map[n] = 1;} // turn on flag to-be-skipped for having all-zero value if (isnan(sumsqr)) {nan_map[n] = 1;} // turn on flag to-be-skipped for containing NaN float fpixdist, fxpix, fypix; int ix, iy; ix = n % cols; iy = n / cols; fxpix = ((float)(ix) -(crpixx - 1.0)) * cdeltx; fypix = ((float)(iy) -(crpixy - 1.0)) * cdelty; fpixdist = fxpix * fxpix + fypix * fypix + 1e-20; fpixdist = sqrt(fpixdist); if (fpixdist > sunarc) {nan_map[n] = 2;} // turn on flag to-be-skipped for being out-of-disk #if RECTANGL == 1 if ((ix < xleftbot) || (ix > xleftbot + xwidth - 1) || (iy < yleftbot) || (iy > yleftbot + yheight - 1)) {nan_map[n] = 3;} // turn on flag to-be-skipped for being out-of-box #endif #if QUICKRUN == 1 // if (n == 15049795) // a non-convergence pixel address of hmi_test.S_720s[2010.05.25_03:00:00_TAI] if ((ix < 1997) || (ix > 2097)) // an example : central 100-pixel width column. {nan_map[n] = 3;} // turn on flag to-be-skipped for being out-of-box #endif #if HARPATCH == 1 && MULTHARP != 1 if ((ix < xleftbot) || (ix > xleftbot + xwidth - 1) || (iy < yleftbot) || (iy > yleftbot + yheight - 1)) { nan_map[n] = 3; } #if HARPBLOB == 1 /* Harp blob or rectanlg */ else { int i2, j2, n2; i2 = ix - xleftbot; j2 = iy - yleftbot; n2 = xwidth * j2 + i2; if (patchmask[n2] < 4) {nan_map[n] = 4;} // check Xudong's definition .... may change without notice ... } #endif #endif // end if HARPATCH is 1 and MULTHARP is NOT 1 #if HARPATCH == 1 && MULTHARP == 1 if (patchmask[n] < 4){nan_map[n] = 4;} // mind that non-blob is assumed somewhere above. #endif #if MASKPTCH == 1 if (patchmask[n] < 2){nan_map[n] = 4;} // the condition at left hand side depends on Xudong's definition. #endif } // end of n-loop printf("data is read\n"); #if MASKPTCH == 1 || HARPATCH == 1 free(patchmask); // liberate #endif /* counting pixels ; on-disk non-NaN out-of-rectanlge masked etc. */ int nonnan, numnan, nofdsk, nofrct, nmask; nonnan = 0; numnan = 0; nofdsk = 0; nofrct = 0; nmask = 0; for (n = 0; n < imgpix; n++) { if (nan_map[n] == 0) nonnan = nonnan + 1; if (nan_map[n] == 1) numnan = numnan + 1; if (nan_map[n] == 2) nofdsk = nofdsk + 1; if (nan_map[n] == 3) nofrct = nofrct + 1; if (nan_map[n] == 4) nmask = nmask + 1; } printf(" Num of pixel total (4k x 4k or 16 x 2^20) : %8d \n", imgpix); printf(" Num of pixel out-of-disk : %8d \n", nofdsk); printf(" Num of pixel out-of-rectangle of interest : %8d \n", nofrct); printf(" Num of pixel skipped due to all-zero or NaN : %8d \n", numnan); printf(" Num of pixel skipped due to mask map : %8d \n", nmask); printf(" Num of pixel to be processed : %8d \n", nonnan); /* make istart and iend list so that the to-be processed pixel will be evenly distributed to PEs */ int irank; int *itmps; int *itmpe; itmps = (int *)malloc(sizeof(int) * mpi_size); itmpe = (int *)malloc(sizeof(int) * mpi_size); for(irank = 0; irank < mpi_size; irank++) { int myrank, nprocs, numpix; int istart, iend; myrank = irank; nprocs = mpi_size; numpix = nonnan; para_range(myrank,nprocs,numpix,&istart,&iend); itmps[irank] = istart; itmpe[irank] = iend; } int icount; icount = -1; for (n = 0; n < imgpix; n++) { if (nan_map[n] == 0) { icount = icount + 1; for (m = 0; m < mpi_size; m++) { if (itmps[m] == icount){istartall[m]=n;} if (itmpe[m] == icount){iendall[m]=n;} } } } free(itmps); // liberate free(itmpe); /* make job assignment list */ #if CYCLPRLL == 1 jobnum = -100000; // negative in order that the later part will be derailed, to detect if the value is not properly given ... for debugging purpose { // scope limiter int modjob; modjob = nonnan % mpi_size; if (modjob == 0){jobnum = nonnan / mpi_size;}else{jobnum = nonnan / mpi_size + 1;} // maybe.. OK jobassignmap = (int *)malloc(sizeof(int) * jobnum * mpi_size); int icount, n, nlast; nlast = -1; icount = -1; for (n = 0; n < imgpix; n++) { if (nan_map[n] == 0) // pixel to be processed. { icount = icount + 1; int npe, ndo, ntemp; npe = icount % mpi_size; // PE, starting with 0 ndo = icount / mpi_size; // serial number at each PE, starting with 0 ntemp = ndo + npe * jobnum; // address stored to-do list. ... jobassignmap[ntemp] = n; // n is in original input Stokes address. nlast = n; // remember the address. } } icount = icount + 1; if (icount != nonnan){printf("%d %d\n",icount,nonnan); DIE("Mistake at new parallel job assignment, at debug point 13 \n");} if (icount < 0){DIE("Mistake at new parallel job assignment, at debug point 14 !\n");} printf(" Modulo JobNum = %d %d \n",modjob, jobnum); if (modjob > 0) // do padding ... by the last valid pixel address { int ntemp, n; for (ntemp = 0; ntemp < (mpi_size - modjob); ntemp++) { int npadding; npadding = (jobnum * mpi_size - 1) - ntemp * jobnum; jobassignmap[npadding] = nlast; } } } // end of scope limiter #endif // end if CYCLPRLL is 1 } // end if mpi_rank == 0 else { // on non-Primary Process Element drms_server_end_transaction(drms_env, 1, 0); // Kehcheng and Arts' suggestion: db_disconnect(&drms_env->session->db_handle); // disconnect from all non-primary PE to DRMS } MPI_Barrier(MPI_COMM_WORLD); // wait until primary PE did a lot of things. /* at this moment, the PE(s) other than the primary do not know the values of imgpix etc.*/ int *ibuff; ibuff=(int *)malloc(sizeof(int)*4); ibuff[0]=imgpix; // packing box ibuff[1]=nvar; ibuff[2]=cols; ibuff[3]=rows; MPI_Bcast(ibuff,4,MPI_INT,0,MPI_COMM_WORLD); imgpix = ibuff[0]; // unpacking nvar = ibuff[1]; cols = ibuff[2]; rows = ibuff[3]; free(ibuff); #if CYCLPRLL == 1 ibuff=(int *)malloc(sizeof(int)*1); ibuff[0]=jobnum; // packing even though the size is 1 MPI_Bcast(ibuff,1,MPI_INT,0,MPI_COMM_WORLD); jobnum = ibuff[0]; free(ibuff); #endif /* sending the istart-iend list array */ MPI_Bcast(istartall,mpi_size,MPI_INT,0,MPI_COMM_WORLD); MPI_Bcast(iendall, mpi_size,MPI_INT,0,MPI_COMM_WORLD); /* sending geometric info. from primary (0th) to other PEs */ float *fbuff; fbuff=(float *)malloc(sizeof(float)*6); fbuff[0] = crpixx; fbuff[1] = crpixy; fbuff[2] = cdeltx; fbuff[3] = cdelty; fbuff[4] = rsun_ref; fbuff[5] = dsun_obs; MPI_Bcast(fbuff,6,MPI_FLOAT,0,MPI_COMM_WORLD); crpixx = fbuff[0]; crpixy = fbuff[1]; cdeltx = fbuff[2]; cdelty = fbuff[3]; rsun_ref = fbuff[4]; dsun_obs = fbuff[5]; free(fbuff); MPI_Barrier(MPI_COMM_WORLD); /* large array allocation, ONLY on the primary PE */ if (mpi_rank == 0) { FinalErr=(double *)malloc(sizeof(double)*imgpix*Err_ct); FinalRes=(double *)malloc(sizeof(double)*imgpix*paramct); FinalConvFlag =(int *)malloc(sizeof(int)*imgpix); FinalConfidMap=(int *)malloc(sizeof(int)*imgpix); FinalQualMap =(int *)malloc(sizeof(int)*imgpix); } /* allocate local array on ALL PE. */ float *dataLocal; float *vlos_initLocal; float *mgst_initLocal; double *FinalResLocal,*FinalErrLocal; int *FinalConvFlagLocal; int *FinalQualMapLocal; int *nan_mapLocal; myrank = mpi_rank; nprocs = mpi_size; numpix = imgpix; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend=iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif #if CYCLPRLL == 1 if (verbose) { printf("Hello, this is %2d th PE of %2d, in charge of %9d pixels, of 0 to %9d.\n", mpi_rank,mpi_size,jobnum,(imgpix-1)); } #else if (verbose) { printf("Hello, this is %2d th PE of %2d, in charge of pixels from %9d to %9d of 0 to %9d.\n", mpi_rank,mpi_size,istart,iend,(imgpix-1)); } #endif int imgpixlocal; imgpixlocal = iend - istart + 1; FinalConvFlagLocal=(int *)malloc(sizeof(int) *imgpixlocal); FinalQualMapLocal =(int *)malloc(sizeof(int) *imgpixlocal); nan_mapLocal = (int *)malloc(sizeof(int) *imgpixlocal); dataLocal = (float *)malloc(sizeof(float) *imgpixlocal*nvar); vlos_initLocal= (float *)malloc(sizeof(float) *imgpixlocal); mgst_initLocal= (float *)malloc(sizeof(float) *imgpixlocal); FinalErrLocal = (double *)malloc(sizeof(double)*imgpixlocal*Err_ct); FinalResLocal = (double *)malloc(sizeof(double)*imgpixlocal*paramct); /* tiny arrays used at processing each pixel as the invert()'s arguments. */ obs = (double *)malloc (sizeof (double) * nvar); res = (double *)calloc (paramct, sizeof (double)); scat= (double *)malloc (sizeof (double) * nvar); err = (double *)calloc (Err_ct,sizeof (double)); weights = (double *)malloc (sizeof (double) * 4); // new one!!! on Feb 10, 2011 MPI_Barrier(MPI_COMM_WORLD); #if TAKEPREV == 1 double *PrevErrLocal, *PrevResLocal, *preverr, *prevres; PrevErrLocal=(double *)malloc(sizeof(double)*imgpixlocal*Err_ct); PrevResLocal=(double *)malloc(sizeof(double)*imgpixlocal*paramct); preverr = (double *)calloc (Err_ct,sizeof (double)); prevres = (double *)malloc (sizeof (double) * paramct); MPI_Barrier(MPI_COMM_WORLD); ibuff=(int *)malloc(sizeof(int)*1); ibuff[0] = iexistprev; MPI_Bcast(ibuff,1,MPI_INT,0,MPI_COMM_WORLD); iexistprev = ibuff[0]; //.... silly free(ibuff); MPI_Barrier(MPI_COMM_WORLD); #endif #if CYCLPRLL == 1 int *jobassignmapLocal; jobassignmapLocal = (int *)malloc(sizeof(int) * jobnum); /* send assignment list from primary PE to the others */ if (mpi_rank == 0) { myrank = mpi_rank; nprocs = mpi_size; numpix = imgpix; istart=0; iend =jobnum-1; /* first, the primary makes copy for its own part */ for (n = istart ; n < iend+1 ; n++){jobassignmapLocal[n -istart] = jobassignmap[n];} /* then send the partials to the other PEs */ if (mpi_size > 1) { int irank; for(irank = 1; irank < mpi_size; irank++) { int mpi_dest; int ibufsize; int *ibufsend; mpi_dest = irank; istart=0; iend =jobnum-1; ibufsize = (iend-istart+1) * 1; ibufsend= (int*)malloc(sizeof(int) * ibufsize); for (n = istart ; n < iend+1 ; n++){ibufsend[n -istart] = jobassignmap[n+mpi_dest*jobnum];} // jobnum = ibufsize = iend-istart+1 mpi_tag = 1000 + irank; MPI_Send(ibufsend, ibufsize, MPI_INTEGER, mpi_dest, mpi_tag, MPI_COMM_WORLD); free(ibufsend); } } } else { /* non-primary PEs wait until served */ int mpi_from = 0; int ibufsize; int *ibufrecv; istart=0; iend =jobnum-1; ibufsize = (iend-istart+1) * 1; ibufrecv = (int*)malloc(sizeof(int) * ibufsize); // printf(" at MPIrank Ibuffsize = %d %d\n",mpi_rank,ibufsize); mpi_tag = 1000 + mpi_rank; MPI_Recv(ibufrecv, ibufsize, MPI_INTEGER, mpi_from, mpi_tag, MPI_COMM_WORLD, &mpistat); for (n = istart ; n < iend+1 ; n++){jobassignmapLocal[n-istart] = ibufrecv[n-istart];} free(ibufrecv); } // end-if mpi_rank is 0, or not. MPI_Barrier(MPI_COMM_WORLD); if (mpi_rank == 0) printf(" job assignment address data had propagated to all PE.\n"); #endif // end-if CYCLPRLL is 1 /* send partial input data to each PE */ if (mpi_rank == 0) { myrank = mpi_rank; nprocs = mpi_size; numpix = imgpix; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend=iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif /* first, the primary makes copy for its own part */ #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++){for (m = 0; m < nvar; m++){dataLocal[(n-istart)*nvar+m] = data[jobassignmap[n] + m*imgpix];}} #else for (n = istart ; n < iend+1 ; n++){for (m = 0; m < nvar; m++){dataLocal[(n-istart)*nvar+m] = data[n + m*imgpix];}} #endif /* then send the partials to the other PEs */ if (mpi_size > 1) { int irank; for(irank = 1; irank < mpi_size; irank++) { int mpi_dest; int ibufsize; float *fbufsend; mpi_dest = irank; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[mpi_dest]; iend=iendall[mpi_dest]; #else para_range(mpi_dest,nprocs,numpix,&istart,&iend); #endif #endif ibufsize = (iend-istart+1) * nvar; fbufsend= (float*)malloc(sizeof(float) * ibufsize); #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++){for (m = 0; m < nvar; m++){fbufsend[(n-istart)*nvar+m] = data[jobassignmap[n+jobnum*mpi_dest] + m*imgpix];}} #else for (n = istart ; n < iend+1 ; n++){for (m = 0; m < nvar; m++){fbufsend[(n-istart)*nvar+m] = data[n + m*imgpix];}} #endif mpi_tag = 1400 + irank; MPI_Send(fbufsend, ibufsize, MPI_REAL, mpi_dest, mpi_tag, MPI_COMM_WORLD); free(fbufsend); } } } else { int mpi_from = 0; int ibufsize; float *fbufrecv; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend=iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif ibufsize = (iend-istart+1) * nvar; fbufrecv = (float*)malloc(sizeof(float) * ibufsize); mpi_tag = 1400 + mpi_rank; MPI_Recv(fbufrecv, ibufsize, MPI_REAL, mpi_from, mpi_tag, MPI_COMM_WORLD, &mpistat); for (n = istart ; n < iend+1 ; n++){for (m = 0; m < nvar; m++){dataLocal[(n-istart)*nvar+m] = fbufrecv[(n-istart)*nvar+m];}} free(fbufrecv); } // end-if mpi_rank is 0, or not. MPI_Barrier(MPI_COMM_WORLD); if (mpi_rank == 0) printf("input data had propagated to all PE.\n"); /* send partial non-NAN mask-map from primary PE to the others */ if (mpi_rank == 0) { myrank = mpi_rank; nprocs = mpi_size; numpix = imgpix; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend=iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif /* first, the primary makes copy for its own part */ #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++){nan_mapLocal[n -istart] = nan_map[jobassignmap[n]];} #else for (n = istart ; n < iend+1 ; n++){nan_mapLocal[n -istart] = nan_map[n];} #endif /* then send the partials to the other PEs */ if (mpi_size > 1) { int irank; for(irank = 1; irank < mpi_size; irank++) { int mpi_dest; int ibufsize; int *ibufsend; mpi_dest = irank; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[mpi_dest]; iend=iendall[mpi_dest]; #else para_range(mpi_dest,nprocs,numpix,&istart,&iend); #endif #endif ibufsize = (iend-istart+1) * 1; ibufsend= (int*)malloc(sizeof(int) * ibufsize); #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++){ibufsend[n -istart] = nan_map[jobassignmap[n+jobnum*mpi_dest]];} #else for (n = istart ; n < iend+1 ; n++){ibufsend[n -istart] = nan_map[n];} #endif mpi_tag = 1500 + irank; MPI_Send(ibufsend, ibufsize, MPI_INTEGER, mpi_dest, mpi_tag, MPI_COMM_WORLD); free(ibufsend); } } } else { /* non-primary PEs wait until served */ int mpi_from = 0; int ibufsize; int *ibufrecv; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend=iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif ibufsize = (iend-istart+1) * 1; ibufrecv = (int*)malloc(sizeof(int) * ibufsize); mpi_tag = 1500 + mpi_rank; MPI_Recv(ibufrecv, ibufsize, MPI_INTEGER, mpi_from, mpi_tag, MPI_COMM_WORLD, &mpistat); for (n = istart ; n < iend+1 ; n++){nan_mapLocal[n-istart] = ibufrecv[n-istart];} free(ibufrecv); } // end-if mpi_rank is 0, or not. MPI_Barrier(MPI_COMM_WORLD); if (mpi_rank == 0) printf("mask data had propagated to all PE.\n"); #if TAKEPREV == 1 /* send prev. results to each PE */ if (mpi_rank == 0) { myrank = mpi_rank; nprocs = mpi_size; numpix = imgpix; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend=iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif /* first, the primary makes copy for its own part */ #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++){for (m = 0; m < paramct; m++){PrevResLocal[(n-istart)*paramct+m] = prevdata[jobassignmap[n] + m *imgpix];}} for (n = istart ; n < iend+1 ; n++){for (m = 0; m < Err_ct; m++){PrevErrLocal[(n-istart)*Err_ct +m] = prevdata[jobassignmap[n] +(m+paramct)*imgpix];}} #else for (n = istart ; n < iend+1 ; n++){for (m = 0; m < paramct; m++){PrevResLocal[(n-istart)*paramct+m] = prevdata[n + m *imgpix];}} for (n = istart ; n < iend+1 ; n++){for (m = 0; m < Err_ct; m++){PrevErrLocal[(n-istart)*Err_ct +m] = prevdata[n +(m+paramct)*imgpix];}} #endif /* then send the partials to the other PEs */ if (mpi_size > 1) { int irank; for(irank = 1; irank < mpi_size; irank++) { int mpi_dest; int ibufsize; float *fbufsend; mpi_dest = irank; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[mpi_dest]; iend=iendall[mpi_dest]; #else para_range(mpi_dest,nprocs,numpix,&istart,&iend); #endif #endif ibufsize = (iend-istart+1) * (paramct + Err_ct); fbufsend= (float*)malloc(sizeof(float) * ibufsize); #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++){for (m = 0; m < (paramct + Err_ct); m++){fbufsend[(n-istart)*(paramct + Err_ct)+m] = prevdata[jobassignmap[n+jobnum*mpi_dest] + m*imgpix];}} #else for (n = istart ; n < iend+1 ; n++){for (m = 0; m < (paramct + Err_ct); m++){fbufsend[(n-istart)*(paramct + Err_ct)+m] = prevdata[n + m*imgpix];}} #endif mpi_tag = 1600 + irank; MPI_Send(fbufsend, ibufsize, MPI_REAL, mpi_dest, mpi_tag, MPI_COMM_WORLD); free(fbufsend); } } } else { int mpi_from = 0; int ibufsize; float *fbufrecv; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend=iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif ibufsize = (iend-istart+1) * (paramct + Err_ct); fbufrecv = (float*)malloc(sizeof(float) * ibufsize); mpi_tag = 1600 + mpi_rank; MPI_Recv(fbufrecv, ibufsize, MPI_REAL, mpi_from, mpi_tag, MPI_COMM_WORLD, &mpistat); for (n = istart ; n < iend+1 ; n++){for (m = 0; m < paramct; m++){PrevResLocal[(n-istart)*paramct+m] = fbufrecv[(n-istart)*(paramct + Err_ct)+m ];}} for (n = istart ; n < iend+1 ; n++){for (m = 0; m < Err_ct; m++){PrevErrLocal[(n-istart)*Err_ct +m] = fbufrecv[(n-istart)*(paramct + Err_ct)+m+paramct];}} free(fbufrecv); } // end-if mpi_rank is 0, or not. MPI_Barrier(MPI_COMM_WORLD); if (mpi_rank == 0) free(prevdata); // liberate if (mpi_rank == 0) printf("previous inv. data had propagated to all PE.\n"); MPI_Barrier(MPI_COMM_WORLD); #endif /* endif TAKEPREV is 1 or not */ #if VLOSINIT == 1 /* send Doppler velocity, as initial guess, to each PE */ if (mpi_rank == 0) { myrank = mpi_rank; nprocs = mpi_size; numpix = imgpix; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend=iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif /* first, the primary makes copy for its own part */ #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++){vlos_initLocal[n-istart] = vlos_init[jobassignmap[n]];} #else for (n = istart ; n < iend+1 ; n++){vlos_initLocal[n-istart] = vlos_init[n];} #endif /* then send the partials to the other PEs */ if (mpi_size > 1) { int irank; for(irank = 1; irank < mpi_size; irank++) { int mpi_dest; int ibufsize; float *fbufsend; mpi_dest = irank; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[mpi_dest]; iend=iendall[mpi_dest]; #else para_range(mpi_dest,nprocs,numpix,&istart,&iend); #endif #endif ibufsize = (iend-istart+1) * 1; fbufsend= (float*)malloc(sizeof(float) * ibufsize); #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++){fbufsend[n-istart] = vlos_init[jobassignmap[n+jobnum*mpi_dest]];} #else for (n = istart ; n < iend+1 ; n++){fbufsend[n-istart] = vlos_init[n];} #endif mpi_tag = 1900 + irank; MPI_Send(fbufsend, ibufsize, MPI_REAL, mpi_dest, mpi_tag, MPI_COMM_WORLD); free(fbufsend); } } } else { int mpi_from = 0; int ibufsize; float *fbufrecv; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend=iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif ibufsize = (iend-istart+1) * 1; fbufrecv = (float*)malloc(sizeof(float) * ibufsize); mpi_tag = 1900 + mpi_rank; MPI_Recv(fbufrecv, ibufsize, MPI_REAL, mpi_from, mpi_tag, MPI_COMM_WORLD, &mpistat); for (n = istart ; n < iend+1 ; n++){vlos_initLocal[n-istart] = fbufrecv[n-istart];} free(fbufrecv); } // end-if mpi_rank is 0, or not. MPI_Barrier(MPI_COMM_WORLD); if (mpi_rank == 0) free(vlos_init); // liberate if (mpi_rank == 0) printf("VLOS_INIT data had propagated to all PE.\n"); MPI_Barrier(MPI_COMM_WORLD); #endif /* endif VLOSINIT is 1 or not */ #if MGSTINIT == 1 /* send magnetogram data, as initial guess, to each PE */ if (mpi_rank == 0) { myrank = mpi_rank; nprocs = mpi_size; numpix = imgpix; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend=iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif /* first, the primary makes copy for its own part */ #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++){mgst_initLocal[n-istart] = mgst_init[jobassignmap[n]];} #else for (n = istart ; n < iend+1 ; n++){mgst_initLocal[n-istart] = mgst_init[n];} #endif /* then send the partials to the other PEs */ if (mpi_size > 1) { int irank; for(irank = 1; irank < mpi_size; irank++) { int mpi_dest; int ibufsize; float *fbufsend; mpi_dest = irank; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[mpi_dest]; iend=iendall[mpi_dest]; #else para_range(mpi_dest,nprocs,numpix,&istart,&iend); #endif #endif ibufsize = (iend-istart+1) * 1; fbufsend= (float*)malloc(sizeof(float) * ibufsize); #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++){fbufsend[n-istart] = mgst_init[jobassignmap[n+jobnum*mpi_dest]];} #else for (n = istart ; n < iend+1 ; n++){fbufsend[n-istart] = mgst_init[n];} #endif mpi_tag = 2000 + irank; MPI_Send(fbufsend, ibufsize, MPI_REAL, mpi_dest, mpi_tag, MPI_COMM_WORLD); free(fbufsend); } } } else { int mpi_from = 0; int ibufsize; float *fbufrecv; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend=iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif ibufsize = (iend-istart+1) * 1; fbufrecv = (float*)malloc(sizeof(float) * ibufsize); mpi_tag = 2000 + mpi_rank; MPI_Recv(fbufrecv, ibufsize, MPI_REAL, mpi_from, mpi_tag, MPI_COMM_WORLD, &mpistat); for (n = istart ; n < iend+1 ; n++){mgst_initLocal[n-istart] = fbufrecv[n-istart];} free(fbufrecv); } // end-if mpi_rank is 0, or not. MPI_Barrier(MPI_COMM_WORLD); if (mpi_rank == 0) free(mgst_init); // liberate if (mpi_rank == 0) printf("MGST_INIT data had propagated to all PE.\n"); MPI_Barrier(MPI_COMM_WORLD); #endif /* endif MGSTINIT is 1 or not */ /* inversion initializations : must be done by each PE. */ if (mpi_rank == 0) printf("\n----------- inversion initializations ----------------- \n"); vfisvalloc_(&NUM_LAMBDA_FILTER,&NUM_LAMBDA,&NUM_LAMBDA_synth); // new one on April 10, 2012 /* On 2012 Jan 24. When determining noise-level at each pixel, the lines below be disabled. */ #if NLEVPIXL != 1 line_init_(&LAMBDA_0,&LAMBDA_B,&NOISE_LEVEL); if (verbose){printf("done line_init for mpi_rank %d\n",mpi_rank);} wave_init_ (&LAMBDA_MIN_synth,&DELTA_LAMBDA,&NUM_LAMBDA_synth); if (verbose){printf("done wave_init for mpi_rank %d\n",mpi_rank );} filt_init_ (&NUM_LAMBDA_FILTER,&WSPACING, &NUM_LAMBDA); // new one, on April 10, 2012 if (verbose){printf("done filt_init for mpi_rank %d\n",mpi_rank);} #endif /* JM Borrero & RC Elliot Apr 7, 2010 * filt_init should be replaced for a routine, written by Sebastien * that will read from the DMRS the phases, contrasts, etcetera: ONLY READ */ /*S.C. filter function */ int location,column,row,ratio,x0,y0,x1,y1,loc1,loc2,loc3,loc4; double xa,xb,ya,yb,X0,Y0,Rsun; int nx2=256,ny2=256; //format of the phase and contrast maps (nx2=number of columns, ny2=number of rows) int nelemPHASENT =4*nx2*ny2; int nelemCONTRASTT=3*nx2*ny2; referencenlam=7000;//number of wavelengths for Fe I line profile FSR =(double *)malloc(7 *sizeof(double)); lineref =(double *)malloc(referencenlam *sizeof(double)); wavelengthref=(double *)malloc(referencenlam *sizeof(double)); phaseNT =(double *)malloc(nelemPHASENT *sizeof(double)); contrastNT =(double *)malloc(nelemPHASENT *sizeof(double)); contrastT =(double *)malloc(nelemCONTRASTT*sizeof(double)); wavelengthbd =(double *)malloc(201 *sizeof(double)); blockerbd =(double *)malloc(201 *sizeof(double)); wavelengthd =(double *)malloc(401 *sizeof(double)); frontwindowd =(double *)malloc(401 *sizeof(double)); phaseT =(double *)malloc(nelemCONTRASTT*sizeof(double)); printf("We should be running initialize_vfisv_filter\n"); if (mpi_rank == 0) /* for DRMS reasons, the DRMS-access be done only by Primary PE */ { int ierr; ierr = initialize_vfisv_filter( wavelengthd,frontwindowd,&nfront,wavelengthbd,blockerbd, &nblocker,¢erblocker,phaseNT,phaseT,contrastNT,contrastT,FSR,lineref,wavelengthref, &referencenlam,&HCME1,&HCMWB,&HCMNB,&HCMPOL); } /* sending S.C. filter-profile variables from primary (0th) to other PEs, by means of MPI_Bcast */ /* first, 8 integers */ ibuff=(int *)malloc(sizeof(int)*8); ibuff[0]=nfront; ibuff[1]=nblocker; ibuff[2]=centerblocker; ibuff[3]=referencenlam; ibuff[4]=HCME1; ibuff[5]=HCMWB; ibuff[6]=HCMNB; ibuff[7]=HCMPOL; MPI_Bcast(ibuff,8,MPI_INT,0,MPI_COMM_WORLD); nfront =ibuff[0]; nblocker =ibuff[1]; centerblocker=ibuff[2]; referencenlam=ibuff[3]; HCME1 =ibuff[4]; HCMWB =ibuff[5]; HCMNB =ibuff[6]; HCMPOL =ibuff[7]; free(ibuff); /* then, bunch of double arrays */ double *fbigbuf; int bigbufsize; bigbufsize=7+referencenlam+referencenlam+nelemPHASENT+nelemPHASENT+nelemCONTRASTT+201+201+401+401+nelemCONTRASTT; fbigbuf=(double *)malloc(bigbufsize*sizeof(double)); MPI_Barrier(MPI_COMM_WORLD); if (mpi_rank == 0) { int icount; icount = 0; for (i=0;i< 7;i++){fbigbuf[icount]=FSR[i] ;icount++;} for (i=0;i< referencenlam;i++){fbigbuf[icount]=lineref[i] ;icount++;} for (i=0;i< referencenlam;i++){fbigbuf[icount]=wavelengthref[i];icount++;} for (i=0;i< nelemPHASENT;i++){fbigbuf[icount]=phaseNT[i] ;icount++;} for (i=0;i< nelemPHASENT;i++){fbigbuf[icount]=contrastNT[i] ;icount++;} for (i=0;i<nelemCONTRASTT;i++){fbigbuf[icount]=contrastT[i] ;icount++;} for (i=0;i< 201;i++){fbigbuf[icount]=wavelengthbd[i] ;icount++;} for (i=0;i< 201;i++){fbigbuf[icount]=blockerbd[i] ;icount++;} for (i=0;i< 401;i++){fbigbuf[icount]=wavelengthd[i] ;icount++;} for (i=0;i< 401;i++){fbigbuf[icount]=frontwindowd[i] ;icount++;} for (i=0;i<nelemCONTRASTT;i++){fbigbuf[icount]=phaseT[i] ;icount++;} if (icount != bigbufsize) { printf("Icount BigBufSize = %d %d\n",icount,bigbufsize); DIE("Mistake at large float buffer, at debug point 1 !\n"); } } MPI_Barrier(MPI_COMM_WORLD); MPI_Bcast(fbigbuf,bigbufsize,MPI_DOUBLE,0,MPI_COMM_WORLD);// broadcasting from 0th PE to the other. if (mpi_rank > 0) { int icount; icount = 0; for (i=0;i< 7;i++){FSR[i] =fbigbuf[icount];icount++;} for (i=0;i< referencenlam;i++){lineref[i] =fbigbuf[icount];icount++;} for (i=0;i< referencenlam;i++){wavelengthref[i]=fbigbuf[icount];icount++;} for (i=0;i< nelemPHASENT;i++){phaseNT[i] =fbigbuf[icount];icount++;} for (i=0;i< nelemPHASENT;i++){contrastNT[i] =fbigbuf[icount];icount++;} for (i=0;i<nelemCONTRASTT;i++){contrastT[i] =fbigbuf[icount];icount++;} for (i=0;i< 201;i++){wavelengthbd[i] =fbigbuf[icount];icount++;} for (i=0;i< 201;i++){blockerbd[i] =fbigbuf[icount];icount++;} for (i=0;i< 401;i++){wavelengthd[i] =fbigbuf[icount];icount++;} for (i=0;i< 401;i++){frontwindowd[i] =fbigbuf[icount];icount++;} for (i=0;i<nelemCONTRASTT;i++){phaseT[i] =fbigbuf[icount];icount++;} if (icount != bigbufsize) { printf("Icount BigBufSize = %d %d\n",icount,bigbufsize); DIE("Mistake at large float buffer, at debug point 2 !\n"); } } free(fbigbuf); if (verbose){printf("done initialize_vfisv_filter by S.C., for mpi_rank %d\n",mpi_rank);} MPI_Barrier(MPI_COMM_WORLD); /* 2011 May 16, added to calculate normalization factor for filter */ double norm_factor; #if NRMLFLTR == 1 if (mpi_rank == 0) { /* copy from lines by S. Couvidat : some lines here seem omittable, but K.H. just copied everything. */ column = 2048; // MIND these two assume the case input be 4k x 4k, but no need to modify even when the input is not of 4k x 4k: row = 2048; // This part just calculate the filter-normalization factor at the center. ratio = 4096/nx2; // Modified on Sep 8, 2011. Now it assumes that cols and rows will not be necessarily 4k. // ratio = cols/nx2; // should be 16 x0 = (column/ratio); // a column number y0 = (row/ratio); // a row number x1 = x0+1; y1 = y0+1; if(x1 >= nx2){x0 = x0-1; x1 = x1-1;} //we will extrapolate at the edges if(y1 >= ny2){y0 = y0-1; y1 = y1-1;} xa = ((double)x1-(double)(column % ratio)/(double)ratio-(double)x0); xb = ((double)(column % ratio)/(double)ratio); ya = ((double)y1-(double)(row % ratio)/(double)ratio-(double)y0); yb = ((double)(row % ratio)/(double)ratio); loc1 = x0+y0*nx2; loc2 = x1+y0*nx2; loc3 = x0+y1*nx2; loc4 = x1+y1*nx2; phaseNTi[0] = ya*(phaseNT[loc1 ]*xa+phaseNT[loc2 ]*xb) +yb*(phaseNT[loc3 ]*xa+phaseNT[loc4 ]*xb); phaseNTi[1] = ya*(phaseNT[loc1+ nx2*ny2]*xa+phaseNT[loc2+nx2*ny2 ]*xb) +yb*(phaseNT[loc3+ nx2*ny2]*xa+phaseNT[loc4+ nx2*ny2]*xb); phaseNTi[2] = ya*(phaseNT[loc1+2*nx2*ny2]*xa+phaseNT[loc2+2*nx2*ny2]*xb) +yb*(phaseNT[loc3+2*nx2*ny2]*xa+phaseNT[loc4+2*nx2*ny2]*xb); phaseNTi[3] = ya*(phaseNT[loc1+3*nx2*ny2]*xa+phaseNT[loc2+3*nx2*ny2]*xb) +yb*(phaseNT[loc3+3*nx2*ny2]*xa+phaseNT[loc4+3*nx2*ny2]*xb); phaseTi[0] = ya*(phaseT[loc1*3 ]*xa+phaseT[loc2*3 ]*xb)+yb*(phaseT[loc3*3 ]*xa+phaseT[loc4*3 ]*xb); phaseTi[1] = ya*(phaseT[loc1*3+1]*xa+phaseT[loc2*3+1]*xb)+yb*(phaseT[loc3*3+1]*xa+phaseT[loc4*3+1]*xb); phaseTi[2] = ya*(phaseT[loc1*3+2]*xa+phaseT[loc2*3+2]*xb)+yb*(phaseT[loc3*3+2]*xa+phaseT[loc4*3+2]*xb); contrastNTi[0]= ya*(contrastNT[loc1 ]*xa+contrastNT[loc2 ]*xb) +yb*(contrastNT[loc3 ]*xa+contrastNT[loc4 ]*xb); contrastNTi[1]= ya*(contrastNT[loc1+ nx2*ny2]*xa+contrastNT[loc2+ nx2*ny2]*xb) +yb*(contrastNT[loc3+ nx2*ny2]*xa+contrastNT[loc4+ nx2*ny2]*xb); contrastNTi[2]= ya*(contrastNT[loc1+2*nx2*ny2]*xa+contrastNT[loc2+2*nx2*ny2]*xb) +yb*(contrastNT[loc3+2*nx2*ny2]*xa+contrastNT[loc4+2*nx2*ny2]*xb); contrastNTi[3]= ya*(contrastNT[loc1+3*nx2*ny2]*xa+contrastNT[loc2+3*nx2*ny2]*xb) +yb*(contrastNT[loc3+3*nx2*ny2]*xa+contrastNT[loc4+3*nx2*ny2]*xb); contrastTi[0] = ya*(contrastT[loc1 ]*xa+contrastT[loc2 ]*xb) +yb*(contrastT[loc3 ]*xa+contrastT[loc4 ]*xb); contrastTi[1] = ya*(contrastT[loc1+ nx2*ny2]*xa+contrastT[loc2+ nx2*ny2]*xb) +yb*(contrastT[loc3+ nx2*ny2]*xa+contrastT[loc4+ nx2*ny2]*xb); contrastTi[2] = ya*(contrastT[loc1+2*nx2*ny2]*xa+contrastT[loc2+2*nx2*ny2]*xb) +yb*(contrastT[loc3+2*nx2*ny2]*xa+contrastT[loc4+2*nx2*ny2]*xb); X0 = (double)crpixx-1.0; Y0 = (double)crpixy-1.0; Rsun = (double)asin(rsun_ref/dsun_obs)/3.14159265358979e0*180.0*3600.0/cdeltx; //solar radius in pixels distance = sqrt(((double)row-Y0)*((double)row-Y0)+((double)column-X0)*((double)column-X0)); //distance in pixels distance = cos(asin(distance/Rsun)); //cosine of angular distance from disk center vfisv_filter(NUM_LAMBDA_FILTERc,NUM_LAMBDAc,filters,LAMBDA_MINc,DELTA_LAMBDAc, wavelengthd,frontwindowd,nfront,wavelengthbd,blockerbd,nblocker,centerblocker, phaseNTi,phaseTi,contrastNTi,contrastTi,FSR,lineref,wavelengthref,referencenlam,distance,HCME1,HCMWB,HCMNB,HCMPOL); /* do some math to yield normalization factor */ double *sum_filt; sum_filt = (double *)malloc (sizeof (double) * NUM_LAMBDA_FILTER); double sumsum, aveave; for (i = 0; i < NUM_LAMBDA_FILTER; i++) { sum_filt[i] = 0.0; for (j = 0; j < NUM_LAMBDA; j++){sum_filt[i] = sum_filt[i] + filters[i][j]; } } sumsum = 0.0; for (i = 0; i < NUM_LAMBDA_FILTER; i++){sumsum = sumsum + sum_filt[i];} aveave = sumsum / ((double)NUM_LAMBDA_FILTER); if (isnan(aveave) || fabs(aveave) < 1e-10){aveave = 1.0;} // .... just in case, maybe right.. norm_factor = aveave; free(sum_filt); } // end if mpi_rank is 0. /* broadcast the value of norm_factor, from the primary PE to the rest */ { // scope limiter MPI_Barrier(MPI_COMM_WORLD); fbuff=(float *)malloc(sizeof(float)*1); fbuff[0] = norm_factor; MPI_Bcast(fbuff,1,MPI_FLOAT,0,MPI_COMM_WORLD); // broadcasting the norm_factor values, from 0th PE to the others. norm_factor = fbuff[0]; //.... silly free(fbuff); if (verbose) {printf(" normalization factor reaching to %d PE is %f\n",mpi_rank,norm_factor);} MPI_Barrier(MPI_COMM_WORLD); } // end of scope limiter #else norm_factor = 1.0; #endif // end if NRMLFLTR is 1 or not if (mpi_rank == 0){printf(" normalization factor for filter is %f\n", norm_factor);} /* ME inversion initialization */ inv_init_(&NUM_ITERATIONS,&SVD_TOLERANCE,&CHI2_STOP,&POLARIZATION_THRESHOLD,&INTENSITY_THRESHOLD); // new one on April 10, 2012 if (verbose){printf("done inv_init\n");} free_init_(list_free_params); if (verbose){printf("done list_free_params for mpi_rank %d\n", mpi_rank);} /* Changed index of list_free_params to refer to Damping*/ if (list_free_params[3] == 0) voigt_init_(); for (n=0; n< nvar; n++) scat[n]=0.0; MPI_Barrier(MPI_COMM_WORLD); if (mpi_rank == 0) printf("\n----------- inversion initializations done ------------ \n"); /* at last, do inversion in parallel */ if (mpi_rank == 0) printf("\n----------- finally, do inversion in parallel --------- \n"); time(&starttime1); myrank = mpi_rank; nprocs = mpi_size; numpix = imgpix; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend =iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif int pixdone; pixdone = 0; int pix_noconv; pix_noconv = 0; for (n = istart; n < iend + 1; n++) { #if CYCLPRLL == 1 if (nan_mapLocal[n-istart] != 0){printf("something nasty happened at %9d th pixel on %2d th PE, %9d th pixel of original. Ah.\n",n,myrank,jobassignmapLocal[n]);DIE(" ah...");} #endif if (nan_mapLocal[n-istart] == 0) { #if TAKEPREV == 1 if (iexistprev == 1) { for (m = 0; m < paramct; m++){prevres[m]=PrevResLocal[(n-istart)*paramct+m];} // values in this array will be put to guess[] later for (m = 0; m < Err_ct; m++){preverr[m]=PrevErrLocal[(n-istart)*Err_ct +m];} // values in this array shall not be used.... } if (iexistprev == 0) { for (m = 0; m < paramct; m++){prevres[m]=NAN;} for (m = 0; m < Err_ct; m++){preverr[m]=NAN;} } #endif for(m = 0; m < nvar; m++){obs[m]=dataLocal[(n-istart)*nvar+m];} /* JM Borrero & RC Eliiot Apr 7, 2010 */ /* Right before calling invert_ there should be a call to another of Sebastien's program to calculate the filter profiles for the particular pixel "n". The output filters should be in the form: double (Num_lambda_filter,num_lambda). Note that we want the filters evaluated at the following wavelenghts: FOR K=1,Num_Lambda DO WAVELENGTH[K] = Lambda_Min + K*Delta_Lambda/1000 [Units are Angstroms] Lambda_Min, Delta_Lambda, Num_lambda_filter & num_lambda are all defined above */ /* Note: I would avoid sending this program the full 512*512 matrixes (can slow down teh code) but rather the 4 neighboring points to perform the bilinear interpolation */ int nccd; // pixel address in the original input Stokes CCD system. Used in cal. Filter func. and other places. #if CYCLPRLL == 1 nccd = jobassignmapLocal[n]; // MIND that this must be the only one occassion jobassignmapLocal be referred within the for-n-loop. #else nccd = n; #endif /*S.C. filter function */ { /* scope limiter to protect values of nccd. It later turned out we do not need this scope. haha. On Sep 8, 2011 by K.H.*/ int nloc, iloc, jloc; float filoc, fjloc; iloc = nccd % cols; // column address in the input data array, whose size is not necessarily 4k x 4k. jloc = nccd / cols; filoc = (float)(iloc) / (float)(cols); // address(es) in float that must run from 0 to 0.999999 fjloc = (float)(jloc) / (float)(rows); filoc = filoc * 4096.0 + 0.000000001; // then, it be now running from 0.0000001 to 4095.999990001 or somthing alike. fjloc = fjloc * 4096.0 + 0.000000001; iloc = (int)(filoc); // enforce it integer jloc = (int)(fjloc); nloc = iloc + 4096 * jloc; // address in 4k x 4k arrays // if ((n != nloc)){printf("test ... : %d %d %d %d\n",nloc,n,cols,rows);} // if cols=rows=4096, nloc must be equal to n. column =nloc % 4096; // column from 0 to 4095 row =nloc / 4096; // row from 0 to 4095 ratio =4096 / nx2; // should be 16 } // end of scope limiter /*-------------------------------------------------------------*/ /* bilinear interpolation of the phase maps at pixel (x,y) */ /*-------------------------------------------------------------*/ //NB: it depends on how the filtergrams rebinning from 4096*4096 to axist[1]*axist[2] was done in phasemaps.c //find the 4 neighbors (x0,y0), (x0,y1), (x1,y0), and (x1,y1) of (column,row) on the grid of the phase maps, and deal with boundary problems x0 = (column/ratio); //a column number y0 = (row/ratio); //a row number x1 = x0+1; y1 = y0+1; if(x1 >= nx2) { x0 = x0-1; //we will extrapolate at the edges x1 = x1-1; } if(y1 >= ny2) { y0 = y0-1; y1 = y1-1; } xa = ((double)x1-(double)(column % ratio)/(double)ratio-(double)x0); xb = ((double)(column % ratio)/(double)ratio); ya = ((double)y1-(double)(row % ratio)/(double)ratio-(double)y0); yb = ((double)(row % ratio)/(double)ratio); //perform the bilinear interpolation loc1 = x0+y0*nx2; loc2 = x1+y0*nx2; loc3 = x0+y1*nx2; loc4 = x1+y1*nx2; phaseNTi[0] = ya*(phaseNT[loc1 ]*xa+phaseNT[loc2 ]*xb) +yb*(phaseNT[loc3 ]*xa+phaseNT[loc4 ]*xb); phaseNTi[1] = ya*(phaseNT[loc1+ nx2*ny2]*xa+phaseNT[loc2+nx2*ny2 ]*xb) +yb*(phaseNT[loc3+ nx2*ny2]*xa+phaseNT[loc4+ nx2*ny2]*xb); phaseNTi[2] = ya*(phaseNT[loc1+2*nx2*ny2]*xa+phaseNT[loc2+2*nx2*ny2]*xb) +yb*(phaseNT[loc3+2*nx2*ny2]*xa+phaseNT[loc4+2*nx2*ny2]*xb); phaseNTi[3] = ya*(phaseNT[loc1+3*nx2*ny2]*xa+phaseNT[loc2+3*nx2*ny2]*xb) +yb*(phaseNT[loc3+3*nx2*ny2]*xa+phaseNT[loc4+3*nx2*ny2]*xb); phaseTi[0] = ya*(phaseT[loc1*3 ]*xa+phaseT[loc2*3 ]*xb)+yb*(phaseT[loc3*3 ]*xa+phaseT[loc4*3 ]*xb); phaseTi[1] = ya*(phaseT[loc1*3+1]*xa+phaseT[loc2*3+1]*xb)+yb*(phaseT[loc3*3+1]*xa+phaseT[loc4*3+1]*xb); phaseTi[2] = ya*(phaseT[loc1*3+2]*xa+phaseT[loc2*3+2]*xb)+yb*(phaseT[loc3*3+2]*xa+phaseT[loc4*3+2]*xb); contrastNTi[0]= ya*(contrastNT[loc1 ]*xa+contrastNT[loc2 ]*xb) +yb*(contrastNT[loc3 ]*xa+contrastNT[loc4 ]*xb); contrastNTi[1]= ya*(contrastNT[loc1+ nx2*ny2]*xa+contrastNT[loc2+ nx2*ny2]*xb) +yb*(contrastNT[loc3+ nx2*ny2]*xa+contrastNT[loc4+ nx2*ny2]*xb); contrastNTi[2]= ya*(contrastNT[loc1+2*nx2*ny2]*xa+contrastNT[loc2+2*nx2*ny2]*xb) +yb*(contrastNT[loc3+2*nx2*ny2]*xa+contrastNT[loc4+2*nx2*ny2]*xb); contrastNTi[3]= ya*(contrastNT[loc1+3*nx2*ny2]*xa+contrastNT[loc2+3*nx2*ny2]*xb) +yb*(contrastNT[loc3+3*nx2*ny2]*xa+contrastNT[loc4+3*nx2*ny2]*xb); contrastTi[0] = ya*(contrastT[loc1 ]*xa+contrastT[loc2 ]*xb) +yb*(contrastT[loc3 ]*xa+contrastT[loc4 ]*xb); contrastTi[1] = ya*(contrastT[loc1+ nx2*ny2]*xa+contrastT[loc2+ nx2*ny2]*xb) +yb*(contrastT[loc3+ nx2*ny2]*xa+contrastT[loc4+ nx2*ny2]*xb); contrastTi[2] = ya*(contrastT[loc1+2*nx2*ny2]*xa+contrastT[loc2+2*nx2*ny2]*xb) +yb*(contrastT[loc3+2*nx2*ny2]*xa+contrastT[loc4+2*nx2*ny2]*xb); X0 = (double)crpixx-1.0; Y0 = (double)crpixy-1.0; Rsun = (double)asin(rsun_ref/dsun_obs)/3.14159265358979e0*180.0*3600.0/cdeltx; //solar radius in pixels distance = sqrt(((double)row-Y0)*((double)row-Y0)+((double)column-X0)*((double)column-X0)); //distance in pixels distance = cos(asin(distance/Rsun)); //cosine of angular distance from disk center //NB: filters[NUM_LAMBDA_FILTERc,NUM_LAMBDAc] are calculated by order of increasing wavelength, from I5 to I0. vfisv_filter(NUM_LAMBDA_FILTERc,NUM_LAMBDAc,filters,LAMBDA_MINc,DELTA_LAMBDAc, wavelengthd,frontwindowd,nfront,wavelengthbd,blockerbd,nblocker,centerblocker, phaseNTi,phaseTi,contrastNTi,contrastTi,FSR,lineref,wavelengthref,referencenlam,distance,HCME1,HCMWB,HCMNB,HCMPOL); /* According to Sebastien: the filters are provided by order of INCREASING WAVELENGTH: the format is filters[i][j] where i is the filter number (i=0 is for I5, centered at -170 mA roughly, i=1 is for I4, ... i=5 is for I0, centered at +170 mA roughly) and j is the wavelength (in order of increasing wavelength from Lambda_Min). */ // By RCE, Apr 23, 2010: Normalize all filters to central filter area hard-coded value: /* The integrated areas of the six filters for the central pixel (pixel # 8386559) are: 1.43858806880917 1.49139978559615 1.52324167542270 1.52811487224149 1.50984871281028 1.46553486521323 the average area being: 1.49279. We will normalize ALL the filters by this value. This is done inside the FORTRAN code, in invert.f90 */ /* By RCE, Apr 21, 2010: added input parameter "filters" to call to "invert_" to pass Sebastien's filter profiles to the inversion module*/ //printf("FILTERS before invert_: filters[0][0] = %f, filters[0][1] = %f, filters[0][25] = %f\n", filters[0][0], filters[0][1], filters[0][25]); //printf("FILTERS before invert_: filters[2][0] = %f, filters[2][1] = %f, filters[2][25] = %f\n", filters[2][0], filters[2][1], filters[2][25]); //printf("FILTERS before invert_: filters[5][0] = %f, filters[5][1] = %f, filters[5][48] = %f\n", filters[5][0], filters[5][1], filters[5][48]); /* JM Borrero & RC Elliot Apr 7, 2010 */ /* invert_ should be called in a new way: invert_ (obs,scat,guess,filter,res,err) where filter should be a 2D double array with dimensions (Num_lambda_filter,num_lambda) eg (6,49) */ //if (verbose){printf("Hello, this is %2d th PE : now doing %9d th pixel \n", mpi_rank, n);} // this is only for debugging purpose int iconverge_flag; /* modified on Nov 2, 2010, re-modified on May 16, 2011. 0: Reached convergence with chi2<EPSILON 1: Continuum intensity not above threshold. Pixel not inverted. 2: Reached maximum number of iterations 3: Finished with too many consecutive non-converging iterations 4: NaN in chi2 determination.. exited loop. 5: NaN in SVDSOL.. exited loop MIND that previous definition must be never used !!! */ /* since 2011 March 3, the weighting array is filled here */ // weights[0]=1.0; weights[1]=7.0; weights[2]=7.0; weights[3]=3.0; // choice 1 // weights[0]=1.0; weights[1]=5.0; weights[2]=5.0; weights[3]=3.0; // choice 2 // weights[0]=1.0; weights[1]=3.0; weights[2]=3.0; weights[3]=2.0; // choice 3 weights[0]=1.0; weights[1]=5.0; weights[2]=5.0; weights[3]=3.5; // choice 3 new !! #if VLOSINIT == 1 guess[6] = vlos_initLocal[n-istart]; // 7th one .. #endif #if MGSTINIT == 1 guess[5] = mgst_initLocal[n-istart]; // 6th one .. #endif /* since 2012 Jan 24, to calculate noise-level at each pixel, the lines below were added */ #if NLEVPIXL == 1 double ivalmax, ivalave, CONT; ivalmax = -100.0e0; ivalave = 0.0e0; { // scope limiter int m; for (m = 0; m < NUM_LAMBDA_FILTER; m++) // very rarely, mostly for test purpose, NUM_LAMBDA_FILTER be other than 6. { double tmpval=obs[0*NUM_LAMBDA_FILTER+m]; // obs(0:5) for Stokes I0 to I5 (or Ix, in an order defined somewhere above) ivalave = ivalave + tmpval; if (tmpval > ivalmax){ivalmax = tmpval;} } CONT = ivalmax; ivalave = ivalave / ((double)(NUM_LAMBDA_FILTER)); ivalave = sqrt(ivalave); ivalmax = sqrt(ivalmax); } // end of scope limiter NOISE_LEVEL[0] = NOISE_LEVELFI * ivalave; NOISE_LEVEL[1] = NOISE_LEVELFQ * ivalave; NOISE_LEVEL[2] = NOISE_LEVELFU * ivalave; NOISE_LEVEL[3] = NOISE_LEVELFV * ivalave; // By RCE: to initialize limits lim_init_(&CONT); line_init_(&LAMBDA_0,&LAMBDA_B,NOISE_LEVEL); // MIND now the third argument is of 4-element double array. wave_init_ (&LAMBDA_MIN_synth,&DELTA_LAMBDA,&NUM_LAMBDA_synth); filt_init_ (&NUM_LAMBDA_FILTER,&WSPACING, &NUM_LAMBDA); #endif /* added on May 17, 2011. * All filter are normalized here. */ #if NRMLFLTR == 1 for (i = 0; i < NUM_LAMBDA_FILTER; i++){for (j = 0; j < NUM_LAMBDA; j++) { filters[i][j] = filters[i][j] / norm_factor; } } #endif invert_ (obs, scat, guess, res, err, filters, &iconverge_flag, weights); // added the weights. on Feb 10, 2011 /* normalization for err array, this must be temporal : later done inisde invert_(), 2011 Sept 7, by K.H. */ // err[0] = err[0] / 1500.0; // field strength in gauss, ERR(1) in Fortran // err[1] = err[1] / 90.0; // inclination angle in degree, ERR(2) in Fortran // err[2] = err[2] / 90.0; // azithum angle in degree, ERR(3) in Fortran // err[0] = err[0] / 38.729833462; // field strength in gauss, ERR(1) in Fortran // err[1] = err[1] / 9.486832981; // inclination angle in degree, ERR(2) in Fortran // err[2] = err[2] / 9.486832981; // azithum angle in degree, ERR(3) in Fortran /* angular error cap, 2012 April 13, by K.H. */ if (err[0] > 12000.0) {err[0] = 12000.0;} if (err[1] > 180.0) {err[1] = 180.0;} if (err[2] > 180.0) {err[2] = 180.0;} /* here do thing in accordance with the value of iconverge_flag. Some NaN-filling be done under wrapper's responsibility by K.H. */ if ((iconverge_flag == 4) || (iconverge_flag == 5) || (iconverge_flag == 1)) // changed on 2011 May 16, responding to the changes in invert.f90 by RCE. { if (verbose){printf("Hello, this is %2d th PE : found iconverge_flag %d at %9d th pixel.\n", mpi_rank, iconverge_flag, nccd);} for (j=0; j<paramct; j++){res[j]=NAN;} for (k=0; k<Err_ct; k++){err[k]=NAN;} } FinalConvFlagLocal[n-istart]=iconverge_flag; /* Here we assume this line is the first line giving value to q-map. QualMap value will be overwritten below */ if (iconverge_flag > 0) { pix_noconv = pix_noconv + 1; FinalQualMapLocal[n-istart]=0x00000002; } else { FinalQualMapLocal[n-istart]=0x00000000; } for (j=0; j<paramct; j++){FinalResLocal[(n-istart)*paramct+j]=res[j];} // copy results to the local-small array(s) for (k=0; k<Err_ct; k++){FinalErrLocal[(n-istart)*Err_ct +k]=err[k];} pixdone = pixdone + 1; } else { float aa=NAN; FinalConvFlagLocal[n-istart]=1; // let it be same as low-signal case FinalQualMapLocal [n-istart]=(int)(aa); // tweaks, working ... this will be later overwritten for (j=0; j<paramct; j++){FinalResLocal[(n-istart)*paramct+j]=NAN;} // put NAN for (k=0; k<Err_ct; k++){FinalErrLocal[(n-istart)*Err_ct +k]=NAN;} } // end of if (NAN) etc. } // end of n-loop if (verbose){printf("Hello, this is %2d th PE : inversion done for %9d pixels. \n", mpi_rank, pixdone);} if (verbose){printf("Hello, this is %2d th PE : Num of pixel at which solution did not converge = %d\n",mpi_rank,pix_noconv);} time(&endtime1); if (verbose){printf("Hello, this is %2d th PE : Time spent %ld\n",mpi_rank,endtime1-starttime1);} MPI_Barrier(MPI_COMM_WORLD); /* count non-convergent pixel etc. */ int sum_pix_noconv; int sum_pixdone; { // limit the scope of some integer variables int *ibufs, *ibufr; ibufs = (int *)malloc(sizeof(int)*2); ibufr = (int *)malloc(sizeof(int)*2); ibufs[0] = pix_noconv; ibufs[1] = pixdone; MPI_Reduce(ibufs,ibufr,2,MPI_INT,MPI_SUM,0,MPI_COMM_WORLD); // only 0th PE will know the total. if (mpi_rank == 0) { sum_pix_noconv = ibufr[0]; sum_pixdone = ibufr[1]; printf("Total num. of pixel processed = %d\n",sum_pixdone); printf("Total num. of pixel at which solution did not converge = %d\n",sum_pix_noconv); } } // end of scope limiter MPI_Barrier(MPI_COMM_WORLD); /* arrays used in S.C. filter function */ free(FSR); free(phaseNT); free(contrastNT); free(phaseT); free(contrastT); free(wavelengthbd); free(blockerbd); free(wavelengthd); free(frontwindowd); free(lineref); free(wavelengthref); /* output data are gathered to primary from each PE */ if (mpi_rank == 0) { myrank = mpi_rank; nprocs = mpi_size; numpix = imgpix; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend=iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif /* first, copy the portion the primary itself did */ #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++) { for (j=0; j<paramct; j++){FinalRes[(jobassignmap[n]*paramct)+j]=FinalResLocal[(n-istart)*paramct+j];} for (k=0; k<Err_ct ; k++){FinalErr[(jobassignmap[n]*Err_ct) +k]=FinalErrLocal[(n-istart)*Err_ct +k];} } #else for (n = istart ; n < iend+1 ; n++) { for (j=0; j<paramct; j++){FinalRes[(n *paramct)+j]=FinalResLocal[(n-istart)*paramct+j];} for (k=0; k<Err_ct ; k++){FinalErr[(n *Err_ct) +k]=FinalErrLocal[(n-istart)*Err_ct +k];} } #endif /* then collecting the portions done by the other PEs */ if (mpi_size > 1) { printf("now collecting float data from PEs : "); int irecv; for (irecv = 1; irecv < mpi_size ; irecv++) { printf(" %d ",irecv); int mpi_from; nprocs = mpi_size; numpix = imgpix; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[irecv]; iend=iendall[irecv]; #else para_range(irecv,nprocs,numpix,&istart,&iend); #endif #endif int ibufsize; ibufsize = (iend-istart+1) * (paramct+Err_ct); double *dbufrecv; dbufrecv = (double*)malloc(sizeof (double) * ibufsize); mpi_from = irecv; mpi_tag = 1200 + irecv; MPI_Recv(dbufrecv, ibufsize, MPI_DOUBLE, mpi_from, mpi_tag, MPI_COMM_WORLD, &mpistat); #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++) { for (j=0; j<paramct; j++){FinalRes[(jobassignmap[n+jobnum*mpi_from]*paramct)+j]=dbufrecv[(n-istart)*(paramct+Err_ct) +j];} for (k=0; k<Err_ct ; k++){FinalErr[(jobassignmap[n+jobnum*mpi_from]*Err_ct) +k]=dbufrecv[(n-istart)*(paramct+Err_ct)+paramct+k];} } #else for (n = istart ; n < iend+1 ; n++) { for (j=0; j<paramct; j++){FinalRes[(n *paramct)+j]=dbufrecv[(n-istart)*(paramct+Err_ct) +j];} for (k=0; k<Err_ct ; k++){FinalErr[(n *Err_ct) +k]=dbufrecv[(n-istart)*(paramct+Err_ct)+paramct+k];} } #endif free(dbufrecv); } printf("done \n"); } } else { int isend; int mpi_dest = 0; nprocs = mpi_size; numpix = imgpix; isend = mpi_rank; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[isend]; iend=iendall[isend]; #else para_range(isend,nprocs,numpix,&istart,&iend); #endif #endif int ibufsize; ibufsize = (iend-istart+1) * (paramct+Err_ct); double *dbufsend; dbufsend = (double*)malloc(sizeof (double) * ibufsize); for (n = istart ; n < iend + 1 ; n++) { for (j=0; j<paramct; j++){dbufsend[(n-istart)*(paramct+Err_ct) +j]=FinalResLocal[(n-istart)*paramct+j];} for (k=0; k<Err_ct; k++){dbufsend[(n-istart)*(paramct+Err_ct)+paramct+k]=FinalErrLocal[(n-istart)*Err_ct +k];} } mpi_tag = 1200 + mpi_rank; MPI_Send(dbufsend, ibufsize, MPI_DOUBLE, mpi_dest, mpi_tag, MPI_COMM_WORLD); free(dbufsend); } // end-if mpi_rank is 0, or not. MPI_Barrier(MPI_COMM_WORLD); // silly..but always safe /* collecting integer array(s) in the same way */ if (mpi_rank == 0) { myrank = mpi_rank; nprocs = mpi_size; numpix = imgpix; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[myrank]; iend=iendall[myrank]; #else para_range(myrank,nprocs,numpix,&istart,&iend); #endif #endif /* first, copy the portion the primary itself did */ #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++) { FinalConvFlag[jobassignmap[n]] = FinalConvFlagLocal[n-istart]; FinalQualMap [jobassignmap[n]] = FinalQualMapLocal [n-istart]; } #else for (n = istart ; n < iend+1 ; n++) { FinalConvFlag[n] = FinalConvFlagLocal[n-istart]; FinalQualMap [n] = FinalQualMapLocal [n-istart]; } #endif /* then collecting the portions done by the other PE */ if (mpi_size > 1) { printf("now collecting integer data from PEs : "); int irecv; for (irecv = 1; irecv < mpi_size ; irecv++) { printf(" %d ",irecv); int mpi_from; nprocs = mpi_size; numpix = imgpix; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[irecv]; iend=iendall[irecv]; #else para_range(irecv,nprocs,numpix,&istart,&iend); #endif #endif int ibufsize; ibufsize = (iend-istart+1) * 2; // so far 2 integer-array be handled ... int *ibufrecv; ibufrecv = (int*)malloc(sizeof(int) * ibufsize); mpi_from = irecv; mpi_tag = 1300 + irecv; MPI_Recv(ibufrecv, ibufsize, MPI_INT, mpi_from, mpi_tag, MPI_COMM_WORLD, &mpistat); #if CYCLPRLL == 1 for (n = istart ; n < iend+1 ; n++) { FinalConvFlag[jobassignmap[n+jobnum*mpi_from]] = ibufrecv[n-istart]; FinalQualMap [jobassignmap[n+jobnum*mpi_from]] = ibufrecv[n-istart+(iend-istart+1)]; } #else for (n = istart ; n < iend+1 ; n++) { FinalConvFlag[n] = ibufrecv[n-istart]; FinalQualMap [n] = ibufrecv[n-istart+(iend-istart+1)]; } #endif // end if CYCLPRLL is 1 or not free(ibufrecv); } printf("done \n"); } } else { int isend; int mpi_dest = 0; nprocs = mpi_size; numpix = imgpix; isend = mpi_rank; #if CYCLPRLL == 1 istart=0; iend =jobnum-1; #else #if EQUIAREA == 1 istart=istartall[isend]; iend=iendall[isend]; #else para_range(isend,nprocs,numpix,&istart,&iend); #endif #endif int ibufsize; ibufsize = (iend-istart+1) * 2; // so far 2 integer-array be handled ... int *ibufsend; ibufsend = (int*)malloc(sizeof (int) * ibufsize); for (n = istart ; n < iend + 1 ; n++) { ibufsend[n-istart ]=FinalConvFlagLocal[n-istart]; ibufsend[n-istart+(iend-istart+1)]=FinalQualMapLocal [n-istart]; } mpi_tag = 1300 + mpi_rank; MPI_Send(ibufsend, ibufsize, MPI_INT, mpi_dest, mpi_tag, MPI_COMM_WORLD); free(ibufsend); } // end-if mpi_rank is 0, or not. MPI_Barrier(MPI_COMM_WORLD); // silly..but always safe /* the primary PE takes care of pixels none had taken care of */ if (mpi_rank == 0) { #if CYCLPRLL == 1 for (n = 0 ; n < imgpix; n++) { if (nan_map[n] != 0) // pixel not to be processed. { float aa=NAN; FinalConvFlag[n] = 1; // (int)(aa); // tweak, working FinalQualMap [n] = (int)(aa); for (j=0; j<paramct; j++){FinalRes[(n*paramct)+j]=NAN;} for (k=0; k<Err_ct ; k++){FinalErr[(n*Err_ct) +k]=NAN;} } } #else if (istartall[0] > 0) { for (n = 0 ; n < istartall[0]; n++) { float aa=NAN; FinalConvFlag[n] = 1; // (int)(aa); // tweak, working FinalQualMap [n] = (int)(aa); for (j=0; j<paramct; j++){FinalRes[(n*paramct)+j]=NAN;} for (k=0; k<Err_ct ; k++){FinalErr[(n*Err_ct) +k]=NAN;} } } if (iendall[mpi_size-1] < imgpix - 1) { for (n = iendall[mpi_size-1] + 1; n < imgpix; n++) { float aa=NAN; FinalConvFlag[n] = 1; // (int)(aa); FinalQualMap [n] = (int)(aa); for (j=0; j<paramct; j++){FinalRes[(n*paramct)+j]=NAN;} for (k=0; k<Err_ct ; k++){FinalErr[(n*Err_ct) +k]=NAN;} } } #endif // end if CYCLPRLL is 1 or not } // end-if mpi_rank is 0. MPI_Barrier(MPI_COMM_WORLD); // silly..but always safe /* clean up arrays */ free(FinalConvFlagLocal); free(FinalQualMapLocal); free(FinalResLocal); free(FinalErrLocal); free(dataLocal); free(nan_mapLocal); #if CYCLPRLL == 1 free(jobassignmapLocal); #endif MPI_Barrier(MPI_COMM_WORLD); /* finalizing confidence and qualily info. maps */ #if CONFINDX == 1 if (mpi_rank == 0) // only the primary PE has all info needed. { #define invCode0 0x0000 // inversion convergence #define invCode2 0x0002 // reached maximum number of iterations #define invCode3 0x0003 // finished with too many consecutive non-converging iterations #define invCode4 0x0004 // NaN in the computation of chi2. exited loop #define invCode5 0x0005 // NaN in SVDSOL. exited loop #define invCode1 0x0001 // continuum intensity not above the required threshold. pixel not inverted #define pixCode0 0x0000 // good pixel #define pixCode1 0x0008 // bad pixel #define quCode0 0x0000 // good QU-signal #define quCode1 0x0010 // low QU-signal #define vCode0 0x0000 // good V-signal #define vCode1 0x0020 // low V-signal #define blosCode0 0x0000 //good Blos value #define blosCode1 0x0040 //low Blos value #define missCode0 0x0000 // Not A missing data #define missCode1 0x0080 // Missing data #define pixThreshold 500.0 // Threshold value for determining bad pixels #define quvScale 0.204 // scaling factor for the Stokes quv noise; sigma(Q,U,V) = 0.204 * sqrt(I) #define iScale 0.118 // scaling factor for Stokes I noise; sigma(I) = 0.118 * sqrt(I) //#define quThreshold 132.0 // The median of qu in a quiet Sun area near the disk center, where // qu = sqrt((sum[i=0, ..., 5] q_i)^2 + (sum[i=0, ..., 5] u_i)^2)) //#define vThreshold 153.0 // The median of v in a quiet Sun area near the disk center, where v = sum[i =0, .., 5] stokesV_i #define losThreshold 1.0 * 6.7 // 1 * sigma of 720s los mags. #define RADSINDEG 3.14159265358979 / 180.0 int yOff = 0, iData = 0; int invQual, pixQual, quQual, vQual, blosQual, missQual; int nx = cols; int ny = rows; for (iData = 0; iData < imgpix; iData++) { float stokesV, stokesU, stokesQ, stokesI; stokesI = 0.0; stokesQ = 0.0; stokesU = 0.0; stokesV = 0.0; // float stokesQU; // stokesQU = 0.0; int m; for (m = 0; m < NUM_LAMBDA_FILTER; m++) { stokesI = stokesI + data[iData +(m+NUM_LAMBDA_FILTER*0)*imgpix]; stokesQ = stokesQ + data[iData +(m+NUM_LAMBDA_FILTER*1)*imgpix]; stokesU = stokesU + data[iData +(m+NUM_LAMBDA_FILTER*2)*imgpix]; stokesV = stokesV + fabs(data[iData +(m+NUM_LAMBDA_FILTER*3)*imgpix]); } // stokesQU = sqrt(stokesU*stokesU + stokesQ*stokesQ); float bLos = blosgram[ iData]; double bTotal = FinalRes[(iData*paramct)+5]; // field strenth in gauss double bIncl = FinalRes[(iData*paramct)+1]; // inclination in degree... int bInvFlag = FinalConvFlag[iData]; FinalConfidMap[iData] = 0; invQual = invCode0; pixQual = pixCode0; quQual = quCode0; vQual = vCode0; blosQual = blosCode0; missQual = missCode0; if (isnan(bTotal) || isnan(bIncl) || isnan(bLos) || isnan(stokesI) || isnan(stokesQ) || isnan(stokesU) || isnan(stokesV) || isnan(bInvFlag)) { missQual = missCode1; FinalQualMap[iData] = invQual | pixQual | quQual | vQual | blosQual | missQual; FinalConfidMap[iData] = 6; } else { // compute the noise level float sigmaLP = 0.0, sigmaV = 0.0; float Qall = 0.0, Uall = 0.0, varQUVall = 0.0, LP = 0.0, Vall = 0.0; Qall = stokesQ; Uall = stokesU; Vall = stokesV; LP = sqrt(Qall * Qall + Uall * Uall); varQUVall = quvScale * quvScale * stokesI; sigmaLP = sqrt(varQUVall); sigmaV = sqrt(varQUVall); //end of noise computation if (bInvFlag == 2) invQual = invCode2; if (bInvFlag == 3) invQual = invCode3; if (bInvFlag == 4) invQual = invCode4; if (bInvFlag == 5) invQual = invCode5; if (bInvFlag == 1) invQual = invCode1; if ((fabs(bLos) - fabs(bTotal * cos(bIncl * RADSINDEG)) > pixThreshold)) pixQual = pixCode1; if (LP < sigmaLP) quQual = quCode1; if (Vall < sigmaV) vQual = vCode1; if (fabs(bLos) < losThreshold) blosQual = blosCode1; FinalQualMap[iData] = invQual | pixQual | quQual | vQual | blosQual | missQual; if ((pixQual == 0) && (invQual == 0)) { if ((vQual != 0) && (quQual == 0) && (blosQual == 0)) FinalConfidMap[iData] = 1; // neutral line or other places where only one if ((vQual == 0) && (quQual != 0) && (blosQual == 0)) FinalConfidMap[iData] = 1; // component is strong. 1 may be as good as 0. if ((vQual == 0) && (quQual == 0) && (blosQual != 0)) FinalConfidMap[iData] = 1; if ((vQual != 0) && (quQual != 0) && (blosQual == 0)) FinalConfidMap[iData] = 2; // neutral line or other places where only one if ((vQual == 0) && (quQual != 0) && (blosQual != 0)) FinalConfidMap[iData] = 2; // component is strong. 2 may be as good as 0. if ((vQual != 0) && (quQual == 0) && (blosQual != 0)) FinalConfidMap[iData] = 2; if ((vQual != 0) && (quQual != 0) && (blosQual != 0)) FinalConfidMap[iData] = 3; } if ((pixQual == 0) && (invQual != 0)) FinalConfidMap[iData] = 4; if (pixQual != 0) FinalConfidMap[iData] = 5; } } // end for-loop /* On 2011 Oct 10, 24-bit shift is made to make room for disambiguation index */ for (iData = 0; iData < imgpix; iData++) { int ival = FinalQualMap[iData]; if (!isnan(ival)){FinalQualMap[iData] = ival * 256 * 256 * 256;} // if (!isnan(ival)){FinalQualMap[iData] = ival << 24;} // elegant, but dangerous } } // end if mpi_rank is zero MPI_Barrier(MPI_COMM_WORLD); #endif // end if CONFINDX is 1 or not /* write outputs through DRMS-JSOC */ if (mpi_rank == 0) { outRec = drms_create_record (drms_env, outser, DRMS_PERMANENT, &status); if (!outRec) {fprintf (stderr, "Error creating record in series %s; abandoned\n",outser);return 1;} /* succeed a lot of keyword info. from the input data record */ drms_copykeys(outRec, inRec, 0, kDRMS_KeyClass_Explicit); // Phil's solution ! /* calculate some full-disk summations */ double blos_ave=0.0; double babs_ave=0.0; double vlos_ave=0.0; {// scope limiter int icount1=0; int icount2=0; int n, nend; for(n = 0; n < imgpix ; n++) { int inan = nan_map[n]; if (inan == 0) { float babs =FinalRes[(n*paramct)+5]; // field strenth in gauss float tht =FinalRes[(n*paramct)+1]; // inclination in degree... if (!isnan(babs) && !isnan(tht)) { float costh, thtr, blos; thtr = tht / 180.0 * 3.14159265358979e0; costh = cos(thtr); blos = - babs * costh; // MIND the sign icount1 = icount1 + 1; babs_ave = babs_ave + babs; blos_ave = blos_ave + blos; } float vlos = FinalRes[(n*paramct)+6]; // vlos if (!isnan(vlos)) { icount2 = icount2 + 1; vlos_ave = vlos_ave + vlos; } } } if (icount1 > 0) { babs_ave=babs_ave/(double)(icount1); blos_ave=blos_ave/(double)(icount1); } else { babs_ave=0.0; blos_ave=0.0; } if (icount2 > 0) { vlos_ave=vlos_ave/(double)(icount2); } else { vlos_ave=0.0; } }// end of scope limiter /* overriding existing keyword, or adding new ones */ { // scope limiter /* version info., given in this code */ char invcodeversion[50]; sprintf(invcodeversion,"%s %s",module_name,version_id); drms_setkey_string(outRec,"INVCODEV", invcodeversion); /* version info. and code location, given by CVS version control */ char *sdummy; sdummy= meinversion_version(); drms_setkey_string(outRec,"CODEVER4", sdummy); /* comment and history */ sdummy=" "; drms_setkey_string(outRec,"HISTORY",sdummy); sdummy="VFISV ME-inversion optimized for HMI data is described in Solar Phys. (2011) vol.273 pp.267-293, Borrero et.al. The 10 fitting parameters are eta_0,inclination,azimuth,damping,dop_width,field,vlos_mag,src_continuum,src_grad,alpha_mag"; drms_setkey_string(outRec,"COMMENT",sdummy); sdummy="HMI observable"; drms_setkey_string(outRec,"CONTENT",sdummy); /* Inversion settings */ drms_setkey_int (outRec,"INVFREEP",keyfreep); drms_setkey_int (outRec,"INVITERA",NUM_ITERATIONS); drms_setkey_int (outRec,"INVLMBDA",NUM_LAMBDA); drms_setkey_int (outRec,"INVLMBDF",NUM_LAMBDA_FILTER); drms_setkey_int (outRec,"INVTUNEN",NUM_TUNNING); drms_setkey_double(outRec,"INVSVDTL",SVD_TOLERANCE); drms_setkey_double(outRec,"INVCHIST",CHI2_STOP); drms_setkey_double(outRec,"INVPOLTH",POLARIZATION_THRESHOLD); drms_setkey_double(outRec,"INVPJUMP",PERCENTAGE_JUMP); drms_setkey_double(outRec,"INVLMBDM",LAMBDA_MIN); drms_setkey_double(outRec,"INVLMBD0",LAMBDA_0); drms_setkey_double(outRec,"INVLMBDB",LAMBDA_B); drms_setkey_double(outRec,"INVDLTLA",DELTA_LAMBDA); drms_setkey_double(outRec,"INVLYOTW",LYOTFWHM); drms_setkey_double(outRec,"INVWNARW",WNARROW); drms_setkey_double(outRec,"INVWSPAC",WSPACING); drms_setkey_double(outRec,"INVINTTH",INTENSITY_THRESHOLD); #if NLEVPIXL == 1 drms_setkey_double(outRec,"INVNFCTI",NOISE_LEVELFI); drms_setkey_double(outRec,"INVNFCTQ",NOISE_LEVELFQ); drms_setkey_double(outRec,"INVNFCTU",NOISE_LEVELFU); drms_setkey_double(outRec,"INVNFCTV",NOISE_LEVELFV); #else drms_setkey_double(outRec,"INVNOISE",NOISE_LEVEL); #endif drms_setkey_int (outRec,"INVCONTI",CONTINUUM); drms_setkey_int (outRec,"INVLMBDS",NUM_LAMBDA_synth); drms_setkey_double(outRec,"INVLMBMS",LAMBDA_MIN_synth); /* added on Feb 10 */ double weighti, weightu, weightq, weightv; weighti = weights[0]; weightq = weights[1]; weightu = weights[2]; weightv = weights[3]; drms_setkey_double(outRec,"INVWGHTI",weighti); drms_setkey_double(outRec,"INVWGHTQ",weightq); drms_setkey_double(outRec,"INVWGHTU",weightu); drms_setkey_double(outRec,"INVWGHTV",weightv); /* added on Feb 10 */ sdummy="No"; drms_setkey_string(outRec,"INVSTLGT",sdummy); sdummy=" "; drms_setkey_string(outRec,"INVFLPRF",sdummy); sdummy=" "; drms_setkey_string(outRec,"INVPHMAP",sdummy); /* some index about inversion outputs */ drms_setkey_double(outRec,"INVVLAVE",vlos_ave); drms_setkey_double(outRec,"INVBLAVE",blos_ave); drms_setkey_double(outRec,"INVBBAVE",babs_ave); drms_setkey_int (outRec,"INVNPRCS",sum_pixdone); drms_setkey_int (outRec,"INVNCNVG",sum_pixdone-sum_pix_noconv); // number of "converged" pixel /* overwrite and-or copy Stokes keywords */ int iqstokes; iqstokes = drms_getkey_int(inRec,"QUALITY",&status); drms_setkey_int (outRec,"QUAL_S",iqstokes); int iqinversion; iqinversion = iqstokes; // must be later modified given // iqinversion = 0xffffffff; drms_setkey_int (outRec,"QUALITY",iqinversion); // TIME stockstime = drms_getkey_time(inRec,"DATE",&status); char timestr[26]; sprint_time(timestr,stockstime,"UTC",0); drms_setkey_string(outRec,"DATE_S",timestr); sprint_time(timestr,CURRENT_SYSTEM_TIME,"UTC",1); // what time it is now drms_setkey_string(outRec,"DATE" ,timestr); // sdummy=indsdesc; drms_setkey_string(outRec,"SOURCE",sdummy); /* padding future-use keywords */ sdummy="n/a"; drms_setkey_string(outRec,"INVKEYS1",sdummy); drms_setkey_string(outRec,"INVKEYS2",sdummy); drms_setkey_string(outRec,"INVKEYS3",sdummy); int idummy=-666; drms_setkey_int (outRec,"INVKEYI1",idummy); drms_setkey_int (outRec,"INVKEYI2",idummy); drms_setkey_int (outRec,"INVKEYI3",idummy); double ddummy=NAN; drms_setkey_double(outRec,"INVKEYD1",ddummy); drms_setkey_double(outRec,"INVKEYD2",ddummy); drms_setkey_double(outRec,"INVKEYD3",ddummy); /*give keyword (unit, as string) to each segment.... must be same as in jsd, duplicating ... Hmmm*/ sdummy="deg"; drms_setkey_string(outRec,"BUNIT_000",sdummy); // incli drms_setkey_string(outRec,"BUNIT_001",sdummy); // azimuth sdummy="Mx/cm^2"; drms_setkey_string(outRec,"BUNIT_002",sdummy); // field strength sdummy="cm/s"; drms_setkey_string(outRec,"BUNIT_003",sdummy); // doppler LoS velocity sdummy="mA"; drms_setkey_string(outRec,"BUNIT_004",sdummy); // dop_width sdummy="dimensionless"; drms_setkey_string(outRec,"BUNIT_005",sdummy); // eta_0 sdummy="length units"; // "dopper width units" ???? drms_setkey_string(outRec,"BUNIT_006",sdummy); // damping sdummy="DN/s"; // "data unit ????" drms_setkey_string(outRec,"BUNIT_007",sdummy); // scr_cont drms_setkey_string(outRec,"BUNIT_008",sdummy); // scr_grad sdummy="dimensionless"; drms_setkey_string(outRec,"BUNIT_009",sdummy); // alpha_mag sdummy=" "; drms_setkey_string(outRec,"BUNIT_010",sdummy); // chi-sq sdummy="deg"; drms_setkey_string(outRec,"BUNIT_011",sdummy); // incli_err drms_setkey_string(outRec,"BUNIT_012",sdummy); // azimuth_err sdummy="Mx/cm^2"; drms_setkey_string(outRec,"BUNIT_013",sdummy); // strength_err sdummy="cm/s"; drms_setkey_string(outRec,"BUNIT_014",sdummy); // doppler Vlos error sdummy="dimensionless"; drms_setkey_string(outRec,"BUNIT_015",sdummy); // alpha_err sdummy=" "; drms_setkey_string(outRec,"BUNIT_016",sdummy); // field_incl_err drms_setkey_string(outRec,"BUNIT_017",sdummy); // field_azm_err drms_setkey_string(outRec,"BUNIT_018",sdummy); // incl_azim_err drms_setkey_string(outRec,"BUNIT_019",sdummy); // field_alpha_err drms_setkey_string(outRec,"BUNIT_020",sdummy); // incli_alpha_err drms_setkey_string(outRec,"BUNIT_021",sdummy); // azimu_alpha drms_setkey_string(outRec,"BUNIT_022",sdummy); // conv_flag drms_setkey_string(outRec,"BUNIT_023",sdummy); // qual_map drms_setkey_string(outRec,"BUNIT_024",sdummy); // confidence index #if ADNEWKWD == 1 drms_setkey_int (outRec,"NHARP",nharp); #endif #if CHNGTREC == 1 drms_setkey_string(outRec, "T_REC",outtrec); // enforce T_REC dummy ones for test #endif } // end of scope-limit char trectmp2[26]; TIME trectmp1 = drms_getkey_time(outRec,"T_REC",&status); sprint_time(trectmp2,trectmp1,"TAI",0); printf("to-be-created record: %s[%s] \n",outser,trectmp2); printf("sending output arrays to DRMS\n"); /* output array will be split to individual array for each j-th parameter */ for (j = 0; j < paramct; j++) { float *dat1; int axes[2]; /* collect the result for each parameter over all pixels */ #if RECTANGL == 1 || HARPATCH == 1 dat1 = (float *)calloc(xwidth * yheight, sizeof(float)); int icount; icount = -1; for(n = 0; n < imgpix ; n++) { int ix, iy; ix = n % cols - xleftbot; iy = n / cols - yleftbot; if ((ix >= 0) && (ix < xwidth) && (iy >= 0) && (iy < yheight)) { icount = icount + 1; dat1[icount] = FinalRes[(n*paramct)+j]; } } axes[0] = xwidth; axes[1] = yheight; #else dat1 = (float *)calloc(imgpix, sizeof(float)); for(n = 0; n < imgpix ; n++){dat1[n] = FinalRes[(n*paramct)+j];} axes[0] = cols; axes[1] = rows; #endif invrt_array = drms_array_create (DRMS_TYPE_FLOAT, 2, axes, dat1, &status); #if INTBSCLE == 1 invrt_array->israw = 0; invrt_array->bzero = bzero_inv[j]; invrt_array->bscale = bscaleinv[j]; #endif outSeg = drms_segment_lookup (outRec, Resname[j]); if (!outSeg) {fprintf(stderr, "Error getting data segment %s; abandoned\n", Resname[j]);} #if ADNEWKWD == 1 set_statistics(outSeg, invrt_array, 1); // 1 at the third argument is for "quick" run #endif if (drms_segment_write (outSeg, invrt_array, 0)) { fprintf (stderr, "Error writing segment %d (%s); abandoned\n", j,outSeg->info->name); return 1; } else { if (verbose){printf("Results written out to %-s\n", Resname[j]);} } free(dat1); } // end of j-loop printf("sending error arrays to DRMS\n"); for (k = 0; k < Err_ct; k++) { float *dat2; int axes[2]; #if RECTANGL == 1 || HARPATCH == 1 dat2 = (float *)calloc(xwidth * yheight, sizeof(float)); int icount; icount = -1; for(n = 0; n < imgpix ; n++) { int ix, iy; ix = n % cols - xleftbot; iy = n / cols - yleftbot; if ((ix >= 0) && (ix < xwidth) && (iy >= 0) && (iy < yheight)) { icount = icount + 1; dat2[icount] = FinalErr[(n*Err_ct)+k]; } } axes[0] = xwidth; axes[1] = yheight; #else dat2 = (float *)calloc(imgpix , sizeof(float)); for (n=0; n < imgpix;n++){dat2[n] = FinalErr[(n*Err_ct)+k];} axes[0] = cols; axes[1] = rows; #endif err_array = drms_array_create (DRMS_TYPE_FLOAT, 2, axes, dat2,&status); #if INTBSCLE == 1 err_array->israw = 0; err_array->bzero = bzero_inv[k+paramct]; err_array->bscale = bscaleinv[k+paramct]; #endif outSeg = drms_segment_lookup (outRec, Resname[k+paramct]); if (!outSeg) { if (verbose){fprintf(stderr, "Error getting data segment %s; abandoned\n", Resname[k+paramct]);} } else { #if ADNEWKWD == 1 set_statistics(outSeg, err_array, 1); // 1 at the third argument is for "quick" run #endif if (drms_segment_write (outSeg, err_array, 0)) { fprintf (stderr, "Error writing to segment %d (%s); abandoned\n", k+paramct, outSeg->info->name); return 1; } else { if (verbose){printf("Errors written out to %-s\n", Resname[k+paramct]);} } } free(dat2); } // end of k-loop printf("sending conv.flag array to DRMS\n"); for (k = Err_ct; k < Err_ct + 1; k++) // behave as if this is (Err_ct+1) th error array. { char *dat3; int axes[2]; #if RECTANGL == 1 || HARPATCH == 1 dat3 = (char *)calloc(xwidth * yheight, sizeof(char)); int icount; icount = -1; for(n = 0; n < imgpix ; n++) { int ix, iy; ix = n % cols - xleftbot; iy = n / cols - yleftbot; if ((ix >= 0) && (ix < xwidth) && (iy >= 0) && (iy < yheight)) { icount = icount + 1; dat3[icount] = (char)FinalConvFlag[n]; // no need of bzero nor bscale ... maybe } } axes[0] = xwidth; axes[1] = yheight; #else dat3 = (char *)calloc(imgpix , sizeof(char)); for (n=0; n < imgpix;n++){dat3[n] = (char)FinalConvFlag[n];} axes[0] = cols; axes[1] = rows; #endif flg_array = drms_array_create (DRMS_TYPE_CHAR, 2, axes, dat3,&status); outSeg = drms_segment_lookup (outRec, Resname[k+paramct]); if (!outSeg) { if (verbose){fprintf(stderr, "Error getting data segment %s; abandoned\n", Resname[k+paramct]);} } else { #if ADNEWKWD == 1 set_statistics(outSeg, flg_array, 1); // 1 at the third argument is for "quick" run #endif if (drms_segment_write (outSeg, flg_array, 0)) { fprintf (stderr, "ConvFlag writing to segment %d (%s); abandoned\n", k+paramct, outSeg->info->name); return 1; } else { if (verbose){printf("ConvFlag written out to %-s\n", Resname[k+paramct]);} } } free(dat3); } // end of k-loop printf("sending info. map array to DRMS\n"); for (k = Err_ct + 1; k < Err_ct + 2; k++) // behave as if this is (Err_ct+2) th error array. { int *dat4; int axes[2]; #if RECTANGL == 1 || HARPATCH == 1 dat4 = (int *)calloc(xwidth * yheight, sizeof(int)); int icount; icount = -1; for(n = 0; n < imgpix ; n++) { int ix, iy; ix = n % cols - xleftbot; iy = n / cols - yleftbot; if ((ix >= 0) && (ix < xwidth) && (iy >= 0) && (iy < yheight)) { icount = icount + 1; dat4[icount] = FinalQualMap[n]; // no need of bzero nor bscale ... maybe } } axes[0] = xwidth; axes[1] = yheight; #else dat4 = (int *)calloc(imgpix , sizeof(int)); for (n=0; n < imgpix;n++){dat4[n] = FinalQualMap[n];} axes[0] = cols; axes[1] = rows; #endif qmap_array = drms_array_create (DRMS_TYPE_INT, 2, axes, dat4,&status); outSeg = drms_segment_lookup (outRec, Resname[k+paramct]); if (!outSeg) { if (verbose){fprintf(stderr, "Error getting data segment %s; abandoned\n", Resname[k+paramct]);} } else { #if ADNEWKWD == 1 set_statistics(outSeg, qmap_array, 1); // 1 at the third argument is for "quick" run #endif if (drms_segment_write (outSeg, qmap_array, 0)) { fprintf (stderr, "QualMap writing to segment %d (%s); abandoned\n", k+paramct, outSeg->info->name); return 1; } else { if (verbose){printf("QualMap written out to %-s\n", Resname[k+paramct]);} } } free(dat4); } // end of k-loop printf("sending confidence index array to DRMS\n"); for (k = Err_ct + 2; k < Err_ct + 3; k++) // behave as if this is (Err_ct+3) th error array. { char *dat5; int axes[2]; #if RECTANGL == 1 || HARPATCH == 1 dat5 = (char *)calloc(xwidth * yheight, sizeof(char)); int icount; icount = -1; for(n = 0; n < imgpix ; n++) { int ix, iy; ix = n % cols - xleftbot; iy = n / cols - yleftbot; if ((ix >= 0) && (ix < xwidth) && (iy >= 0) && (iy < yheight)) { icount = icount + 1; dat5[icount] = (char)FinalConfidMap[n]; // no need of bzero nor bscale ... maybe } } axes[0] = xwidth; axes[1] = yheight; #else dat5 = (char *)calloc(imgpix , sizeof(char)); for (n=0; n < imgpix;n++){dat5[n] = (char)FinalConfidMap[n];} axes[0] = cols; axes[1] = rows; #endif flg_array = drms_array_create (DRMS_TYPE_CHAR, 2, axes, dat5,&status); outSeg = drms_segment_lookup (outRec, Resname[k+paramct]); if (!outSeg) { if (verbose){fprintf(stderr, "Error getting data segment %s; abandoned\n", Resname[k+paramct]);} } else { #if ADNEWKWD == 1 set_statistics(outSeg, flg_array, 1); // 1 at the third argument is for "quick" run #endif if (drms_segment_write (outSeg, flg_array, 0)) { fprintf (stderr, "ConfidenceIndex writing to segment %d (%s); abandoned\n", k+paramct, outSeg->info->name); return 1; } else { if (verbose){printf("ConfidenceIndex written out to %-s\n", Resname[k+paramct]);} } } free(dat5); } // end of k-loop printf("write-out done !\n"); free(FinalErr); // clean up free(FinalRes); free(FinalConvFlag); free(FinalQualMap); free(FinalConfidMap); printf("so, close all DRMS record(s) !\n"); /* DRMS trailer and closer */ drms_close_record (outRec, DRMS_INSERT_RECORD); drms_close_records (inRS, DRMS_FREE_RECORD); /* how long it took */ time(&endtime); printf ("%ld sec for %d profiles\n", endtime - startime, sum_pixdone); printf ("%.2f profiles per second\n", (float)(sum_pixdone) / (0.01 + (float)(endtime - startime))); printf("good bye !\n"); } // end-if mpi_rank is 0. MPI_Barrier(MPI_COMM_WORLD); /* say good bye to MPI things.*/ MPI_Finalize(); return 0; } // end of DoIt /* ------------------------------- end of main-wrapper layer ------------------------------- */ /* ------------------------------- subprograms ------------------------------- */ /* -------------------------------------------------------------------------------- * * Calculate the first and the last addresses of array each PE will be in charge of. * From MPI text book. * By K.H. * * -------------------------------------------------------------------------------- */ void para_range(int myrank, int nprocs, int numpix, int *istart, int *iend) { int iwork1, iwork2, imin, idummy, n1, n2; n1 = 0; // When written in Fortran, this is typically 1. n2 = numpix - 1; // When written in Fortran, this is typically numpix. iwork1 = (n2 - n1 + 1) / nprocs; iwork2 = (n2 - n1 + 1) % nprocs; // mod(n2-n1+1,nprocs) if (iwork2 >= myrank){imin = myrank;}else{imin=iwork2;} // imin = min(myrank,iwork2) *istart = myrank*iwork1 + n1 + imin; idummy = *istart + iwork1 - 1; if (iwork2 <= myrank){*iend = idummy;}else{*iend=idummy+1;} } /* ----------------------------- by Sebastien (1), filter profile etc.---------------------------- */ /*------------------------------------------------------------------------------------------------------*/ /* Function to perform linear interpolation */ /* found on the internet */ /* returns the values yinterp at points x of 1D function yv (at the points xv) */ /*------------------------------------------------------------------------------------------------------*/ void lininterp1f(double *yinterp, double *xv, double *yv, double *x, double ydefault, int m, int minterp) { int i, j; int nrowsinterp, nrowsdata; nrowsinterp = minterp; nrowsdata = m; for (i=0; i<nrowsinterp; i++) { if((x[i] < xv[0]) || (x[i] > xv[nrowsdata-1])) yinterp[i] = ydefault; else { for(j=1; j<nrowsdata; j++) { if(x[i]<=xv[j]) { yinterp[i] = (x[i]-xv[j-1]) / (xv[j]-xv[j-1]) * (yv[j]-yv[j-1]) + yv[j-1]; break; } } } } } /*-------------------------------------------------------------------------------------------------------*/ /* function to read the files and parameters needed to compute the filter transmission profiles */ /*-------------------------------------------------------------------------------------------------------*/ int initialize_vfisv_filter(double *wavelengthd,double *frontwindowd,int *nfront,double *wavelengthbd,double *blockerbd,int *nblocker,double *centerblocker,double *phaseNT,double *phaseT,double *contrastNT,double *contrastT,double *FSR,double *lineref,double *wavelengthref,int *referencenlam,int *HCME1,int *HCMWB,int *HCMNB,int *HCMPOL) { printf("INSIDE initialize_vfisv_filter\n"); int status=1; //status=1 if the code failed, =0 if the code succeeded int nx2=256,ny2=256; //format of the phase and contrast maps int nelemPHASENT =4*nx2*ny2; int nelemCONTRASTT=3*nx2*nx2; int nread,i; int status2=0; char inRecQuery[256]; char query[256]; int nRecs; DRMS_RecordSet_t *data= NULL; char *keyname="HCAMID"; //camera keyword int keyvalue; int recofinterest; FILE *fp=NULL; int FSNphasemaps=3292550; //WARNING: JUST TEMPORARY, NEED A WAY TO DECIDE WHICH FSN TO USE !!!!!!!! int camera=2; //WARNING: 2 MEANS WE ALWAYS USE THE SIDE CAMERA. CHNAGE THAT TO 3 FOR FRONT CAMERA *centerblocker=2.6; //in Angstrom, WARNING: VALUE MIGHT CHANGE *referencenlam=7000;//number of wavelengths for Fe I line profile *nblocker=201; *nfront=401; FSR[0]=0.169; //FSR in Angstroms, NB Michelson WARNING: THESE VALUES MIGHT CHANGE FSR[1]=0.337; //WB Michelson FSR[2]=0.695; //Lyot element E1 FSR[3]=1.407; //E2 FSR[4]=2.779; //E3 FSR[5]=5.682; //E4 FSR[6]=11.354;//E5 char filephasesnontunable[]="/home/couvidat/cvs/JSOC/proj/lev1.5_hmi/apps/non_tunable_phases_710660_June09_cal_256_2.bin"; //binary file containing the phases of the 4 non-tunable elements, format A[element][row][column],AVERAGE FRONT + SIDE CAMERA, 1020", CALMODE, 256x256, with the phases of the tunable elements obtained from an average of the laser detunes char filecontrastsnontunable[]="/home/couvidat/cvs/JSOC/proj/lev1.5_hmi/apps/non_tunable_contrasts_710660_June09_cal_256_2.bin"; //name of the binary file containing the contrasts of the 4 non-tunable elements A[element][row][column], AVERAGE FRONT+ SIDE CAMERA, 1020", CALMODE, 256x256 char filecontraststunable[]="/home/couvidat/cvs/JSOC/proj/lev1.5_hmi/apps/tunable_contrasts_710660_June09_cal_256.bin"; //binary file containing the contrasts of the 3 tunable elements A[element][row][column], AVERAGE FRONT + SIDE CAMERA, 1020", CALMODE, 256x256 //for these 3 files, there must be values up to a radius = solarradiusmax, and values=zero at larger radii char referencesolarline[]="/home/couvidat/cvs/JSOC/proj/lev1.5_hmi/apps/ReferenceFeLine.bin"; //solar line DECONVOLVED of R. Ulrich at disk center and zero velocity, interpolated on a very fine grid with Fourier interpolation, and centered (7000 points, dlam=0.0001 A), binary file, single precision (float) char referencewavelength[]="/home/couvidat/cvs/JSOC/proj/lev1.5_hmi/apps/ReferenceWavelength.bin" ; //wavelength grid for the solar line, binary file, single precision (float) //OPENING OF BINARY FILES CONTAINING Fe I LINE PROFILE float templineref[*referencenlam]; //reference solar line: solar line of R. Ulrich at disk center, zero velocity, interpolated on a fine grid, and centered float tempwavelengthref[*referencenlam];//wavelength grid for the reference wavelength fp = fopen(referencesolarline,"rb"); fread(templineref,sizeof(float),*referencenlam,fp); fclose(fp); fp = fopen(referencewavelength,"rb"); fread(tempwavelengthref,sizeof(float),*referencenlam,fp); fclose(fp); for(i=0;i<*referencenlam;++i) { lineref[i]=(double)templineref[i]; wavelengthref[i]=(double)tempwavelengthref[i]; } //OPENING OF BINARY FILES CONTAINING PHASES AND CONTRASTS OF NON-TUNABLE ELEMENTS printf("READ PHASES OF NON-TUNABLE ELEMENTS\n"); fp = fopen(filephasesnontunable,"rb"); //in float, and 256x256. idl format: phase[256,256,4], so C format: phase[element][row][column] if(fp == NULL) { printf("Error: CANNOT OPEN FILE OF NON-TUNABLE ELEMENT PHASES\n"); return status; } float phaseNTf[nelemPHASENT]; nread=fread(phaseNTf,sizeof(float),nelemPHASENT,fp); fclose(fp); for(i=0;i<nelemPHASENT;++i) phaseNT[i] = (double)phaseNTf[i]*M_PI/180.; //convert phases from degrees to radians printf("READ CONTRASTS OF NON-TUNABLE ELEMENTS\n"); fp = fopen(filecontrastsnontunable,"rb"); //in float, and 256x256. idl format: contrast[256,256,4], so C format: contrast[element][row][column] if(fp == NULL) { printf("Error: CANNOT OPEN FILE OF NON-TUNABLE ELEMENT CONTRASTS\n"); return status; } float contrastNTf[nelemPHASENT]; nread=fread(contrastNTf,sizeof(float),nelemPHASENT,fp); fclose(fp); for(i=0;i<nelemPHASENT;++i) contrastNT[i]=(double)contrastNTf[i]; //OPENING OF BINARY FILE CONTAINING CONTRASTS OF TUNABLE ELEMENTS printf("READ CONTRASTS OF TUNABLE ELEMENTS\n"); fp = fopen(filecontraststunable,"rb"); //in float, and 256x256. idl format: contrast[256,256,3], so C format: contrast[element][row][column] if(fp == NULL) { printf("Eeror: CANNOT OPEN FILE OF NON-TUNABLE ELEMENT PHASES\n"); return status; } float contrastTf[nelemCONTRASTT]; nread=fread(contrastTf,sizeof(float),nelemCONTRASTT,fp); fclose(fp); for(i=0;i<nelemCONTRASTT;++i) contrastT[i]=(double)contrastTf[i]; //BLOCKER FILTER S/N 11 TRANSMISSION PROFILE (from blocker11.txt) double wbd[201]={6150.00,6150.20,6150.40,6150.60,6150.80,6151.00,6151.20,6151.40,6151.60,6151.80,6152.00,6152.20,6152.40,6152.60,6152.80,6153.00,6153.20,6153.40,6153.60,6153.80,6154.00,6154.20,6154.40,6154.60,6154.80,6155.00,6155.20,6155.40,6155.60,6155.80,6156.00,6156.20,6156.40,6156.60,6156.80,6157.00,6157.20,6157.40,6157.60,6157.80,6158.00,6158.20,6158.40,6158.60,6158.80,6159.00,6159.20,6159.40,6159.60,6159.80,6160.00,6160.20,6160.40,6160.60,6160.80,6161.00,6161.20,6161.40,6161.60,6161.80,6162.00,6162.20,6162.40,6162.60,6162.80,6163.00,6163.20,6163.40,6163.60,6163.80,6164.00,6164.20,6164.40,6164.60,6164.80,6165.00,6165.20,6165.40,6165.60,6165.80,6166.00,6166.20,6166.40,6166.60,6166.80,6167.00,6167.20,6167.40,6167.60,6167.80,6168.00,6168.20,6168.40,6168.60,6168.80,6169.00,6169.20,6169.40,6169.60,6169.80,6170.00,6170.20,6170.40,6170.60,6170.80,6171.00,6171.20,6171.40,6171.60,6171.80,6172.00,6172.20,6172.40,6172.60,6172.80,6173.00,6173.20,6173.40,6173.60,6173.80,6174.00,6174.20,6174.40,6174.60,6174.80,6175.00,6175.20,6175.40,6175.60,6175.80,6176.00,6176.20,6176.40,6176.60,6176.80,6177.00,6177.20,6177.40,6177.60,6177.80,6178.00,6178.20,6178.40,6178.60,6178.80,6179.00,6179.20,6179.40,6179.60,6179.80,6180.00,6180.20,6180.40,6180.60,6180.80,6181.00,6181.20,6181.40,6181.60,6181.80,6182.00,6182.20,6182.40,6182.60,6182.80,6183.00,6183.20,6183.40,6183.60,6183.80,6184.00,6184.20,6184.40,6184.60,6184.80,6185.00,6185.20,6185.40,6185.60,6185.80,6186.00,6186.20,6186.40,6186.60,6186.80,6187.00,6187.20,6187.40,6187.60,6187.80,6188.00,6188.20,6188.40,6188.60,6188.80,6189.00,6189.20,6189.40,6189.60,6189.80,6190.00}; double bld[201]={0.0701790,0.0723149,0.0747684,0.0713996,0.0782131,0.0758304,0.0789970,0.0762436,0.0806648,0.0828427,0.0801553,0.0830996,0.0882834,0.0885202,0.0869452,0.0877748,0.0974292,0.0942963,0.0968998,0.0961026,0.100459,0.104028,0.102757,0.107549,0.111349,0.120277,0.117723,0.127142,0.125108,0.135901,0.146540,0.148481,0.151049,0.161267,0.173912,0.191953,0.204322,0.227430,0.239466,0.255259,0.272536,0.311694,0.341673,0.356651,0.409127,0.452214,0.535866,0.614547,0.667113,0.740491,0.847670,0.958023,1.05927,1.19029,1.33457,1.51771,1.90178,2.28149,2.49949,2.80167,3.20520,3.85124,4.35895,4.98798,5.73421,6.53362,8.32412,9.85849,10.6749,12.2367,13.5532,16.0578,17.5336,19.9408,21.4035,26.3633,28.4878,31.9405,33.4455,36.0767,38.4715,42.1947,44.3560,46.8881,49.1468,51.3640,54.9618,57.0772,58.2497,59.3955,60.7570,62.1459,62.7333,63.6812,64.1301,64.7157,65.1849,65.6286,65.4660,65.5828,65.4650,65.4184,65.0766,64.7526,64.0896,63.4954,62.1029,60.4464,59.8266,58.1582,57.0750,54.6480,53.1968,51.1148,49.0429,46.5159,42.3256,38.8035,37.2384,34.5975,32.0762,28.5152,26.2661,23.6695,21.7173,17.3033,15.3031,13.0296,11.8265,10.3604,9.23128,7.53426,6.70699,5.79359,4.97535,4.35803,3.27063,2.70147,2.42119,2.11748,1.83017,1.53329,1.34299,1.19612,1.02633,0.915612,0.711036,0.622389,0.575185,0.507517,0.450262,0.401576,0.365934,0.322949,0.286864,0.272241,0.232461,0.207537,0.189114,0.173546,0.161978,0.152099,0.134795,0.123677,0.110288,0.108344,0.0948288,0.0818621,0.0804488,0.0753219,0.0693417,0.0643225,0.0620898,0.0559437,0.0540745,0.0485797,0.0486797,0.0432530,0.0439143,0.0401164,0.0367754,0.0359879,0.0343058,0.0336281,0.0330711,0.0339798,0.0271329,0.0281424,0.0299408,0.0264017,0.0278133,0.0250958,0.0248676,0.0223389,0.0238825,0.0259792,0.0226330,0.0204282,0.0209307,0.0207487,0.0209464}; for(i=0;i<201;++i) { wavelengthbd[i]=wbd[i]; blockerbd[i]=bld[i]; } //FRONT WINDOW S/N 3 TRANSMISSION PROFILE (from frontwindow3.txt) double wd[401]={607.300,607.350,607.400,607.450,607.500,607.550,607.600,607.650,607.700,607.750,607.800,607.850,607.900,607.950,608.000,608.050,608.100,608.150,608.200,608.250,608.300,608.350,608.400,608.450,608.500,608.550,608.600,608.650,608.700,608.750,608.800,608.850,608.900,608.950,609.000,609.050,609.100,609.150,609.200,609.250,609.300,609.350,609.400,609.450,609.500,609.550,609.600,609.650,609.700,609.750,609.800,609.850,609.900,609.950,610.000,610.050,610.100,610.150,610.200,610.250,610.300,610.350,610.400,610.450,610.500,610.550,610.600,610.650,610.700,610.750,610.800,610.850,610.900,610.950,611.000,611.050,611.100,611.150,611.200,611.250,611.300,611.350,611.400,611.450,611.500,611.550,611.600,611.650,611.700,611.750,611.800,611.850,611.900,611.950,612.000,612.050,612.100,612.150,612.200,612.250,612.300,612.350,612.400,612.450,612.500,612.550,612.600,612.650,612.700,612.750,612.800,612.850,612.900,612.950,613.000,613.050,613.100,613.150,613.200,613.250,613.300,613.350,613.400,613.450,613.500,613.550,613.600,613.650,613.700,613.750,613.800,613.850,613.900,613.950,614.000,614.050,614.100,614.150,614.200,614.250,614.300,614.350,614.400,614.450,614.500,614.550,614.600,614.650,614.700,614.750,614.800,614.850,614.900,614.950,615.000,615.050,615.100,615.150,615.200,615.250,615.300,615.350,615.400,615.450,615.500,615.550,615.600,615.650,615.700,615.750,615.800,615.850,615.900,615.950,616.000,616.050,616.100,616.150,616.200,616.250,616.300,616.350,616.400,616.450,616.500,616.550,616.600,616.650,616.700,616.750,616.800,616.850,616.900,616.950,617.000,617.050,617.100,617.150,617.200,617.250,617.300,617.350,617.400,617.450,617.500,617.550,617.600,617.650,617.700,617.750,617.800,617.850,617.900,617.950,618.000,618.050,618.100,618.150,618.200,618.250,618.300,618.350,618.400,618.450,618.500,618.550,618.600,618.650,618.700,618.750,618.800,618.850,618.900,618.950,619.000,619.050,619.100,619.150,619.200,619.250,619.300,619.350,619.400,619.450,619.500,619.550,619.600,619.650,619.700,619.750,619.800,619.850,619.900,619.950,620.000,620.050,620.100,620.150,620.200,620.250,620.300,620.350,620.400,620.450,620.500,620.550,620.600,620.650,620.700,620.750,620.800,620.850,620.900,620.950,621.000,621.050,621.100,621.150,621.200,621.250,621.300,621.350,621.400,621.450,621.500,621.550,621.600,621.650,621.700,621.750,621.800,621.850,621.900,621.950,622.000,622.050,622.100,622.150,622.200,622.250,622.300,622.350,622.400,622.450,622.500,622.550,622.600,622.650,622.700,622.750,622.800,622.850,622.900,622.950,623.000,623.050,623.100,623.150,623.200,623.250,623.300,623.350,623.400,623.450,623.500,623.550,623.600,623.650,623.700,623.750,623.800,623.850,623.900,623.950,624.000,624.050,624.100,624.150,624.200,624.250,624.300,624.350,624.400,624.450,624.500,624.550,624.600,624.650,624.700,624.750,624.800,624.850,624.900,624.950,625.000,625.050,625.100,625.150,625.200,625.250,625.300,625.350,625.400,625.450,625.500,625.550,625.600,625.650,625.700,625.750,625.800,625.850,625.900,625.950,626.000,626.050,626.100,626.150,626.200,626.250,626.300,626.350,626.400,626.450,626.500,626.550,626.600,626.650,626.700,626.750,626.800,626.850,626.900,626.950,627.000,627.050,627.100,627.150,627.200,627.250,627.300}; double fd[401]={0.0824,0.0939,0.0787,0.1035,0.0712,0.0794,0.1009,0.0841,0.0889,0.0439,0.0884,0.1057,0.1161,0.0858,0.0717,0.1085,0.0939,0.1030,0.1027,0.0805,0.0831,0.1088,0.1005,0.0767,0.0920,0.0755,0.0862,0.1045,0.1125,0.1068,0.0964,0.1106,0.1134,0.0919,0.1147,0.1105,0.1171,0.1166,0.0975,0.1113,0.1094,0.1317,0.1379,0.1335,0.1444,0.1323,0.1103,0.1487,0.1564,0.1551,0.1550,0.1705,0.1672,0.1258,0.1330,0.1428,0.1620,0.1656,0.1843,0.1940,0.1811,0.1908,0.1628,0.1760,0.2049,0.1959,0.2186,0.2341,0.2504,0.2322,0.2292,0.2409,0.2355,0.2490,0.2984,0.2840,0.2854,0.2927,0.2823,0.3015,0.3269,0.3337,0.3787,0.3949,0.3853,0.3833,0.4298,0.4670,0.4692,0.4981,0.5129,0.5428,0.5865,0.6077,0.6290,0.6324,0.7459,0.7480,0.8150,0.8657,0.8920,0.9285,1.0100,1.0616,1.1343,1.2479,1.2852,1.3584,1.4890,1.5699,1.6990,1.8128,1.9565,2.1121,2.2822,2.4738,2.6485,2.9025,3.1073,3.3880,3.6499,3.9427,4.3108,4.6652,4.9989,5.5283,5.9813,6.5033,7.1314,7.7739,8.3984,9.1871,10.0736,10.8755,11.9132,13.0402,13.9753,15.3119,16.5884,17.9287,19.5970,21.4054,22.8304,24.9109,27.0054,28.6829,30.9226,33.2495,35.3898,37.8594,40.3831,42.7200,44.9671,47.5569,49.9864,52.2030,54.7069,57.0780,58.8828,60.8594,62.6620,64.4119,66.2320,68.2963,69.4221,70.8045,72.2034,73.4397,74.4796,75.5385,76.0362,76.8120,77.7408,78.4357,78.7422,79.3253,79.8358,80.3452,80.8023,80.7372,81.0416,81.5797,81.9136,82.0703,82.4872,82.4652,82.5696,82.6470,82.7640,82.8444,82.7465,82.4404,82.6908,82.8926,83.1894,83.3542,83.3569,83.2381,83.3289,83.2983,83.3072,83.4495,83.3260,83.3259,83.2807,83.1566,83.0003,82.8881,82.8700,83.2338,83.6685,83.5310,83.3660,83.4200,83.4753,83.5535,83.4297,83.5024,83.3255,83.3739,83.2229,83.0138,82.7990,83.0881,82.8699,82.5380,82.4950,82.2752,81.6813,81.0162,80.4859,79.8935,79.0734,78.1775,77.1055,75.6790,73.7593,72.1025,70.1430,67.8169,65.3109,62.7376,59.8977,56.6526,53.3823,50.7530,47.4383,43.8974,40.5806,37.9460,34.8128,31.9024,29.1972,26.9859,24.4400,22.1973,20.2288,18.4441,16.6123,14.9844,13.5245,12.4264,11.2253,10.1547,9.2421,8.5064,7.7160,6.9712,6.3549,5.8530,5.3515,4.8613,4.4704,4.1431,3.7857,3.4459,3.1822,2.9684,2.7397,2.5416,2.3371,2.1395,2.0216,1.8965,1.7565,1.6370,1.5414,1.4241,1.3505,1.2548,1.1747,1.1431,1.0586,0.9672,0.9421,0.8876,0.8538,0.8146,0.7764,0.7325,0.6940,0.6494,0.6119,0.6018,0.5367,0.5330,0.5568,0.5291,0.4903,0.4759,0.4601,0.4422,0.3874,0.3670,0.3589,0.3565,0.3655,0.3273,0.3272,0.3035,0.3008,0.3135,0.2618,0.2653,0.2760,0.2466,0.2407,0.2260,0.2107,0.2255,0.2064,0.2066,0.1937,0.1648,0.1614,0.1906,0.1738,0.1403,0.1535,0.1480,0.1581,0.1243,0.1326,0.1140,0.1280,0.1621,0.1404,0.1348,0.1110,0.1075,0.1022,0.1140,0.1186,0.1072,0.1250,0.1132,0.1193,0.0794,0.0808,0.0930,0.0886,0.0693,0.0934,0.0827,0.0644,0.0723,0.0732,0.0574,0.0606,0.0555,0.0536,0.0540,0.0625,0.0444,0.0616,0.0663,0.0506,0.0506,0.0492,0.0294,0.0661,0.0511,0.0556,0.0188,0.0257,0.0414,0.0484,0.0167,0.0341,0.0216,0.0269,0.0308,0.0451,0.0700,0.0326,0.0110,0.0288,0.0414,0.0225,0.0119,0.0509}; for(i=0;i<401;++i) { wavelengthd[i]=wd[i]; frontwindowd[i]=fd[i]; } //OPEN THE DRMS RECORD CONTAINING THE PHASE MAPS OF THE TUNABLE ELEMENTS strcpy(inRecQuery,"su_couvidat.phasemaps["); sprintf(query,"%d",FSNphasemaps); strcat(inRecQuery,query); strcat(inRecQuery,"]"); printf("Phase-map query = %s\n",inRecQuery); data = drms_open_records(drms_env,inRecQuery,&status2); //open the records from the input series if (status2 == DRMS_SUCCESS && data != NULL && data->n > 0) { nRecs = data->n; //number of records in the input series printf("Number of phase-map satisfying the request= %d \n",nRecs); //check if the number of records is appropriate } else { printf("Input phase-map series %s doesn't exist\n",inRecQuery);//if the input series does not exit return status; //we exit the program } DRMS_Segment_t *segin = NULL; DRMS_Array_t *arrin = NULL; float *tempphase = NULL; //LOCATE THE PHASE-MAP RECORD TO USE i=0; while(i<nRecs) { keyvalue = drms_getkey_int(data->records[i],keyname,&status2); if(status2 != 0) { printf("Error: unable to read keyword %s\n",keyname); return status; } if(keyvalue == camera) { recofinterest=i; //the record contains the phase maps obtained from data taken with the camera we want break; } i++; } if(i == nRecs) { printf("Error: no phase-map record was found with the proper FSN_REC and HCAMID\n"); return status; } segin = drms_segment_lookupnum(data->records[recofinterest],0); arrin = drms_segment_read(segin,segin->info->type,&status2); if(status2 != DRMS_SUCCESS) { printf("Error: unable to read a data segment\n"); return status; } tempphase = arrin->data; for(i=0;i<nelemCONTRASTT;++i) phaseT[i] = (double)tempphase[i]*M_PI/180.; //NB: PHASE MAPS ARE ASSUMED TO BE IN TYPE FLOAT AND IN DEGREES *HCMNB=drms_getkey_int(data->records[recofinterest],"HCMNB",&status2); if(status2 != DRMS_SUCCESS) { printf("Error: could not read HMCNB\n"); return status; } *HCMWB=drms_getkey_int(data->records[recofinterest],"HCMWB",&status2); if(status2 != DRMS_SUCCESS) { printf("Error: could not read HMCWB\n"); return status; } *HCME1=drms_getkey_int(data->records[recofinterest],"HCME1",&status2); if(status2 != DRMS_SUCCESS) { printf("Error: could not read HMCE1\n"); return status; } *HCMPOL=0; //WARNING: MAKE SURE IT'S THE CASE drms_free_array(arrin); drms_close_records(data,DRMS_FREE_RECORD); //insert the record in DRMS status=0; return status; } /*-------------------------------------------------------------------------------------------------------*/ /* Function to compute the HMI-filter profiles */ /* */ /* OUTPUT: */ /* filters are the filter profiles, in the format double filters[Num_lambda_filter][Num_lambda] */ /* */ /* INPUTS: */ /* Num_lambda is the number of wavelengths */ /* Lambda_Min is the minimum value of the wavelength */ /* Delta_Lambda is the wavelength resolution (in milliAngstroms) */ /* Num_lambda_filter is the number of filters/wavelengths used */ /* frontwindowd is the spatially-averaged front window transmission profile */ /* wavelengthd is the wavelength grid for the front window profile */ /* nfront is the number of points of the window profile */ /* blockerd is the spatially-averaged blocker filter transmission profile */ /* wavelengthbd is the wavelength grid for the blocker filter profile */ /* nblocker is the number of points of the blocker filter profile */ /* centerblocker is the location of the center of the blocker filter */ /* phaseNT are the phases of the 4 non-tunable elements */ /* phaseT are the phases of the 3 tunable elements */ /* contrastNT are the contrasts of the 4 non-tunable elements */ /* contrastT are the contrasts of the 3 tunable elements */ /* FSR are the full spectral ranges of the 7 HMI optical-filter elements */ /* lineref is the reference Fe I line profile at disk center */ /* wavelengthref is the wavelength grid for the Fe I line profile */ /* referencenlam is the number of wavelengths in the reference Fe I profile */ /* distance is the angular distance from disk center for the pixel studied (distance=cos(theta): 1 at */ /* disk center, 0 at the limb) */ /* HCME1 is the hollow-core motor position to center the profile on the Fe I line for the Lyot element E1*/ /* HCMWB is for the wide-band Michelson */ /* HCMNB is for the NB Michelson */ /* HCMPOL is for the tuning polarizer */ /*-------------------------------------------------------------------------------------------------------*/ int vfisv_filter(int Num_lambda_filter,int Num_lambda,double filters[Num_lambda_filter][Num_lambda],double Lambda_Min,double Delta_Lambda,double *wavelengthd,double *frontwindowd,int nfront,double *wavelengthbd,double *blockerbd,int nblocker,double centerblocker,double phaseNTi[4],double phaseTi[3],double contrastNTi[4],double contrastTi[3],double *FSR,double *lineref,double *wavelengthref,int referencenlam,double distance,int HCME1,int HCMWB,int HCMNB,int HCMPOL) { int status=1; //status=0 means the code succeeded, =1 means the code failed if(Num_lambda_filter != 5 && Num_lambda_filter != 6 && Num_lambda_filter != 8 && Num_lambda_filter != 10) { printf("Error: the number of wavelengths should be either 5, 6, 8, or 10\n"); return status; } double lam0 = 6173.3433; //WAVELENGTH AT REST OF THE SOLAR FeI LINE (THIS IS THE REFERENCE WAVELENGTH THAT IS USED TO CALCULATE THE PHASES OF THE TUNABLE ELEMENTS) double lineprofile[Num_lambda],wavelength[Num_lambda]; double lineprofile2[referencenlam],wavelength2[referencenlam]; double ydefault = 1.; //default value for the intensity of the solar line OUTSIDE a small range around 6173.3433 A (SHOULD BE 1) double ydefault2= 0.; //default value for the transmittance of the blocker filter and front window outside the range considered (SHOULD BE 0) int i,j; //CENTER-TO-LIMB VARIATION OF THE Fe I LINES PROVIDED BY ROGER ULRICH (FWHMS AND LINEDEPTHS OBTAINED BY FITTING A GAUSSIAN) double cost[3]={1.0,0.70710678,0.5}; //cos(theta) where theta is the angular distance from disk center double minimumCoeffs[2]={0.41922611,0.24190794}; //minimum intensity (Id if I=1-Id*exp() ), assuming the continuum is at 1 (result from a Gaussian fit in the range [-0.055,0.055] Angstroms) double FWHMCoeffs[2]={151.34559,-58.521771}; //FWHM of the solar line in milliAngstrom (result from a Gaussian fit in the range [-0.055,0.055] Angstroms) double *HCME1phase=NULL,*HCMWBphase=NULL,*HCMNBphase=NULL; double frontwindowint[Num_lambda]; double blockerint[Num_lambda]; double lyot[Num_lambda]; double FWHM,minimum; //WAVELENGTH GRID // By RCE April 22, 2010: divide Lambda_Min by 1d3 to put it in Angstroems for(i=0;i<Num_lambda;++i) wavelength[i]= Lambda_Min/1000.0 + (double)i*Delta_Lambda/1000.0; //wavelength is the wavelength grid in Angstroms //FRONT WINDOW + BLOCKING FILTER PROFILES #if 0 for(i=0;i<nfront;++i) { wavelengthd[i]=wavelengthd[i]*10.0-lam0; frontwindowd[i]=frontwindowd[i]/100.0; } for(i=0;i<nblocker;++i) { wavelengthbd[i]=wavelengthbd[i]+centerblocker-lam0; blockerbd[i]=blockerbd[i]/100.0; } lininterp1f(frontwindowint,wavelengthd,frontwindowd,wavelength,ydefault2,nfront,Num_lambda); //Interpolation on the same wavelength grid lininterp1f(blockerint,wavelengthbd,blockerbd,wavelength,ydefault2,nblocker,Num_lambda); #else /* added by K.H. April 22, following Rebecca's efforts */ double *wavelengthdtmp, *wavelengthbdtmp, *frontwindowdtmp, *blockerbdtmp; blockerbdtmp=(double *)malloc(201*sizeof(double)); wavelengthbdtmp=(double *)malloc(201*sizeof(double)); wavelengthdtmp=(double *)malloc(401*sizeof(double)); frontwindowdtmp=(double *)malloc(401*sizeof(double)); for(i=0;i<nfront;++i) { wavelengthdtmp[i]=wavelengthd[i]*10.0-lam0; frontwindowdtmp[i]=frontwindowd[i]/100.0; } for(i=0;i<nblocker;++i) { wavelengthbdtmp[i]=wavelengthbd[i]+centerblocker-lam0; blockerbdtmp[i]=blockerbd[i]/100.0; } lininterp1f(frontwindowint,wavelengthdtmp, frontwindowdtmp,wavelength,ydefault2,nfront, Num_lambda); //Interpolation on the same wavelength grid lininterp1f(blockerint, wavelengthbdtmp,blockerbdtmp, wavelength,ydefault2,nblocker,Num_lambda); free(blockerbdtmp); free(wavelengthbdtmp); free(wavelengthdtmp); free(frontwindowdtmp); #endif /* end of edit by K.H. */ for(j=0;j<Num_lambda;++j) { blockerint[j]=blockerint[j]*frontwindowint[j]; } //INTERPOLATION OF THE FeI LINEWIDTH AND LINEDEPTH AT DIFFERENT ANGULAR DISTANCES FROM DISK CENTER FWHM=FWHMCoeffs[0]+FWHMCoeffs[1]*distance; minimum=minimumCoeffs[0]+minimumCoeffs[1]*distance; for(i=0;i<referencenlam;++i) { lineprofile2[i] = (1.0-lineref[i])*minimum/(minimumCoeffs[0]+minimumCoeffs[1]); //scaling by the ratio of linedepths lineprofile2[i] = 1.0-lineprofile2[i]; wavelength2[i] = wavelengthref[i]*FWHM/(FWHMCoeffs[0]+FWHMCoeffs[1]); } //LINEAR INTERPOLATION ONTO THE WAVELENGTH GRID for (i=0;i<Num_lambda;i++) { if((wavelength[i] < wavelength2[0]) || (wavelength[i] > wavelength2[referencenlam-1])) lineprofile[i] = ydefault; else { for(j=1; j<referencenlam; j++) { if(wavelength[i]<=wavelength2[j]) { lineprofile[i] = (wavelength[i]-wavelength2[j-1]) / (wavelength2[j]-wavelength2[j-1]) * (lineprofile2[j]-lineprofile2[j-1]) + lineprofile2[j-1]; break; } } } } //POSITIONS OF THE Num_lambda_filter WAVELENGTHS HCME1phase = (double *) malloc(Num_lambda_filter*sizeof(double)); if(HCME1phase == NULL) { printf("Error: no memory allocated to HCME1phase\n"); exit(EXIT_FAILURE); } HCMWBphase = (double *) malloc(Num_lambda_filter*sizeof(double)); if(HCMWBphase == NULL) { printf("Error: no memory allocated to HCMWBphase\n"); exit(EXIT_FAILURE); } HCMNBphase = (double *) malloc(Num_lambda_filter*sizeof(double)); if(HCMNBphase == NULL) { printf("Error: no memory allocated to HCMNBphase\n"); exit(EXIT_FAILURE); } if(Num_lambda_filter == 6) { HCME1phase[5]= (double) ((HCME1+15)*6 % 360)*M_PI/180.0; //I0 HCME1phase[4]= (double) ((HCME1+9 )*6 % 360)*M_PI/180.0; //I1 HCME1phase[3]= (double) ((HCME1+3 )*6 % 360)*M_PI/180.0; //I2 HCME1phase[2]= (double) ((HCME1-3 )*6 % 360)*M_PI/180.0; //I3 HCME1phase[1]= (double) ((HCME1-9 )*6 % 360)*M_PI/180.0; //I4 HCME1phase[0]= (double) ((HCME1-15)*6 % 360)*M_PI/180.0; //I5 HCMWBphase[5]= (double) ((HCMWB-30)*6 % 360)*M_PI/180.0; HCMWBphase[4]= (double) ((HCMWB-18)*6 % 360)*M_PI/180.0; HCMWBphase[3]= (double) ((HCMWB-6 )*6 % 360)*M_PI/180.0; HCMWBphase[2]= (double) ((HCMWB+6 )*6 % 360)*M_PI/180.0; HCMWBphase[1]= (double) ((HCMWB+18)*6 % 360)*M_PI/180.0; HCMWBphase[0]= (double) ((HCMWB-30)*6 % 360)*M_PI/180.0; HCMNBphase[5]= (double) ((HCMNB-0 )*6 % 360)*M_PI/180.0; HCMNBphase[4]= (double) ((HCMNB+24)*6 % 360)*M_PI/180.0; HCMNBphase[3]= (double) ((HCMNB-12)*6 % 360)*M_PI/180.0; HCMNBphase[2]= (double) ((HCMNB+12)*6 % 360)*M_PI/180.0; HCMNBphase[1]= (double) ((HCMNB-24)*6 % 360)*M_PI/180.0; HCMNBphase[0]= (double) ((HCMNB+0 )*6 % 360)*M_PI/180.0; } if(Num_lambda_filter == 5) { HCME1phase[4]= (double) ((HCME1+12)*6 % 360)*M_PI/180.0; //I0 HCME1phase[3]= (double) ((HCME1+6 )*6 % 360)*M_PI/180.0; //I1 HCME1phase[2]= (double) ((HCME1+0 )*6 % 360)*M_PI/180.0; //I2 HCME1phase[1]= (double) ((HCME1-6 )*6 % 360)*M_PI/180.0; //I3 HCME1phase[0]= (double) ((HCME1-12)*6 % 360)*M_PI/180.0; //I4 HCMWBphase[4]= (double) ((HCMWB-24)*6 % 360)*M_PI/180.0; HCMWBphase[3]= (double) ((HCMWB-12)*6 % 360)*M_PI/180.0; HCMWBphase[2]= (double) ((HCMWB+0 )*6 % 360)*M_PI/180.0; HCMWBphase[1]= (double) ((HCMWB+12)*6 % 360)*M_PI/180.0; HCMWBphase[0]= (double) ((HCMWB+24)*6 % 360)*M_PI/180.0; HCMNBphase[4]= (double) ((HCMNB+12)*6 % 360)*M_PI/180.0; HCMNBphase[3]= (double) ((HCMNB-24)*6 % 360)*M_PI/180.0; HCMNBphase[2]= (double) ((HCMNB+0 )*6 % 360)*M_PI/180.0; HCMNBphase[1]= (double) ((HCMNB+24)*6 % 360)*M_PI/180.0; HCMNBphase[0]= (double) ((HCMNB-12)*6 % 360)*M_PI/180.0; } if(Num_lambda_filter == 8) { HCME1phase[7]= (double) ((HCME1+21)*6 % 360)*M_PI/180.0; //I7 HCME1phase[6]= (double) ((HCME1+15)*6 % 360)*M_PI/180.0; //I0 HCME1phase[5]= (double) ((HCME1+9 )*6 % 360)*M_PI/180.0; //I1 HCME1phase[4]= (double) ((HCME1+3 )*6 % 360)*M_PI/180.0; //I2 HCME1phase[3]= (double) ((HCME1-3 )*6 % 360)*M_PI/180.0; //I3 HCME1phase[2]= (double) ((HCME1-9 )*6 % 360)*M_PI/180.0; //I4 HCME1phase[1]= (double) ((HCME1-15)*6 % 360)*M_PI/180.0; //I5 HCME1phase[0]= (double) ((HCME1-21)*6 % 360)*M_PI/180.0; //I6 HCMWBphase[7]= (double) ((HCMWB+18)*6 % 360)*M_PI/180.0; HCMWBphase[6]= (double) ((HCMWB-30)*6 % 360)*M_PI/180.0; HCMWBphase[5]= (double) ((HCMWB-18)*6 % 360)*M_PI/180.0; HCMWBphase[4]= (double) ((HCMWB-6 )*6 % 360)*M_PI/180.0; HCMWBphase[3]= (double) ((HCMWB+6 )*6 % 360)*M_PI/180.0; HCMWBphase[2]= (double) ((HCMWB+18)*6 % 360)*M_PI/180.0; HCMWBphase[1]= (double) ((HCMWB-30)*6 % 360)*M_PI/180.0; HCMWBphase[0]= (double) ((HCMWB-18)*6 % 360)*M_PI/180.0; HCMNBphase[7]= (double) ((HCMNB-24)*6 % 360)*M_PI/180.0; HCMNBphase[6]= (double) ((HCMNB-0 )*6 % 360)*M_PI/180.0; HCMNBphase[5]= (double) ((HCMNB+24)*6 % 360)*M_PI/180.0; HCMNBphase[4]= (double) ((HCMNB-12)*6 % 360)*M_PI/180.0; HCMNBphase[3]= (double) ((HCMNB+12)*6 % 360)*M_PI/180.0; HCMNBphase[2]= (double) ((HCMNB-24)*6 % 360)*M_PI/180.0; HCMNBphase[1]= (double) ((HCMNB+0 )*6 % 360)*M_PI/180.0; HCMNBphase[0]= (double) ((HCMNB+24 )*6 % 360)*M_PI/180.0; } if(Num_lambda_filter == 10) { HCME1phase[9]= (double) ((HCME1+27)*6 % 360)*M_PI/180.0; //I9 HCME1phase[8]= (double) ((HCME1+21)*6 % 360)*M_PI/180.0; //I7 HCME1phase[7]= (double) ((HCME1+15)*6 % 360)*M_PI/180.0; //I0 HCME1phase[6]= (double) ((HCME1+9 )*6 % 360)*M_PI/180.0; //I1 HCME1phase[5]= (double) ((HCME1+3 )*6 % 360)*M_PI/180.0; //I2 HCME1phase[4]= (double) ((HCME1-3 )*6 % 360)*M_PI/180.0; //I3 HCME1phase[3]= (double) ((HCME1-9 )*6 % 360)*M_PI/180.0; //I4 HCME1phase[2]= (double) ((HCME1-15)*6 % 360)*M_PI/180.0; //I5 HCME1phase[1]= (double) ((HCME1-21)*6 % 360)*M_PI/180.0; //I6 HCME1phase[0]= (double) ((HCME1-27)*6 % 360)*M_PI/180.0; //I8 HCMWBphase[9]= (double) ((HCMWB+6)*6 % 360)*M_PI/180.0; HCMWBphase[8]= (double) ((HCMWB+18)*6 % 360)*M_PI/180.0; HCMWBphase[7]= (double) ((HCMWB-30)*6 % 360)*M_PI/180.0; HCMWBphase[6]= (double) ((HCMWB-18)*6 % 360)*M_PI/180.0; HCMWBphase[5]= (double) ((HCMWB-6 )*6 % 360)*M_PI/180.0; HCMWBphase[4]= (double) ((HCMWB+6 )*6 % 360)*M_PI/180.0; HCMWBphase[3]= (double) ((HCMWB+18)*6 % 360)*M_PI/180.0; HCMWBphase[2]= (double) ((HCMWB-30)*6 % 360)*M_PI/180.0; HCMWBphase[1]= (double) ((HCMWB-18)*6 % 360)*M_PI/180.0; HCMWBphase[0]= (double) ((HCMWB-6)*6 % 360)*M_PI/180.0; HCMNBphase[9]= (double) ((HCMNB+12 )*6 % 360)*M_PI/180.0; HCMNBphase[8]= (double) ((HCMNB-24)*6 % 360)*M_PI/180.0; HCMNBphase[7]= (double) ((HCMNB-0 )*6 % 360)*M_PI/180.0; HCMNBphase[6]= (double) ((HCMNB+24)*6 % 360)*M_PI/180.0; HCMNBphase[5]= (double) ((HCMNB-12)*6 % 360)*M_PI/180.0; HCMNBphase[4]= (double) ((HCMNB+12)*6 % 360)*M_PI/180.0; HCMNBphase[3]= (double) ((HCMNB-24)*6 % 360)*M_PI/180.0; HCMNBphase[2]= (double) ((HCMNB+0 )*6 % 360)*M_PI/180.0; HCMNBphase[1]= (double) ((HCMNB+24 )*6 % 360)*M_PI/180.0; HCMNBphase[0]= (double) ((HCMNB-12)*6 % 360)*M_PI/180.0; } //NON-TUNABLE TRANSMISSION PROFILE for(j=0;j<Num_lambda;++j) { lyot[j]=blockerint[j]*(1.+contrastNTi[0]*cos(2.0*M_PI/FSR[3]*wavelength[j]+phaseNTi[0]))/2.*(1.+contrastNTi[1]*cos(2.0*M_PI/FSR[4]*wavelength[j]+phaseNTi[1]))/2.*(1.+contrastNTi[2]*cos(2.0*M_PI/FSR[5]*wavelength[j]+phaseNTi[2]))/2.*(1.+contrastNTi[3]*cos(2.0*M_PI/FSR[6]*wavelength[j]+phaseNTi[3]))/2.; } //TUNABLE TRANSMISSION PROFILE (NB: FILTERS ARE CALCULATED FROM I0 TO I9 WHICH IS NOT BY ORDER OF INCREASING WAVELENGTH FOR Num_lambda_filter > 6) for(i=0;i<Num_lambda_filter;++i) { for(j=0;j<Num_lambda;++j){ filters[i][j] = lyot[j]*(1.+contrastTi[0]*cos(2.0*M_PI/FSR[0]*wavelength[j]+HCMNBphase[i]+phaseTi[0]))/2.*(1.+contrastTi[1]*cos(2.0*M_PI/FSR[1]*wavelength[j]+HCMWBphase[i]+phaseTi[1]))/2.*(1.+contrastTi[2]*cos(2.0*M_PI/FSR[2]*wavelength[j]-HCME1phase[i]+phaseTi[2]))/2.; } } free(HCMNBphase); free(HCMWBphase); free(HCME1phase); status=0; return status; } /* ----------------------------- by Sebastien (2), CVS version info. ----------------------------- */ char *meinversion_version(){return strdup("$Id: vfisv_fd10_old.c,v 1.1 2013/04/30 20:24:43 keiji Exp $");} /* Maybe some other Fortran version be included, here OR at bottom of this file. Maybe at bottom. */ /* ----------------------------- end of this file ----------------------------- */ /* -------------------------------------------- : voigt.f,v 1.6 2012/04/10 22:16:09 keiji Exp : change_var.f90,v 1.3 2012/04/10 22:16:14 keiji Exp : cons_param.f90,v 1.5 2012/04/10 22:16:19 keiji Exp : filt_init.f90,v 1.6 2012/04/10 22:16:24 keiji Exp : filt_param.f90,v 1.6 2012/04/10 22:16:29 keiji Exp : forward.f90,v 1.6 2012/04/10 22:16:34 keiji Exp : free_init.f90,v 1.5 2012/04/10 22:16:39 keiji Exp : free_memory.f90,v 1.5 2012/04/10 22:16:44 keiji Exp : invert.f90,v 1.8 2012/04/10 22:16:49 keiji Exp : inv_init.f90,v 1.5 2012/04/10 22:16:54 keiji Exp : inv_param.f90,v 1.5 2012/04/10 22:16:59 keiji Exp : inv_utils.f90,v 1.6 2012/04/10 22:17:03 keiji Exp : lim_init.f90,v 1.1 2012/04/10 22:17:08 keiji Exp : line_init.f90,v 1.5 2012/04/10 22:17:12 keiji Exp : line_param.f90,v 1.5 2012/04/10 22:17:18 keiji Exp : ran_mod.f90,v 1.5 2012/04/10 22:17:23 keiji Exp : svbksb.f90,v 1.5 2012/04/10 22:17:28 keiji Exp : svdcmp.f90,v 1.5 2012/04/10 22:17:33 keiji Exp : voigt_data.f90,v 1.5 2012/04/10 22:17:39 keiji Exp : voigt_init.f90,v 1.5 2012/04/10 22:17:46 keiji Exp : voigt_taylor.f90,v 1.6 2012/04/10 22:17:51 keiji Exp : wave_init.f90,v 1.5 2012/04/10 22:17:56 keiji Exp : wfa_guess.f90,v 1.5 2012/04/10 22:18:01 keiji Exp -------------------------------------------- */
Karen Tian |
Powered by ViewCVS 0.9.4 |