// I would like to put it all in a struct, but then I'd have to write a constructor for it, due to members defined as
// references, creating a worse nightmare than the one I'd like to simplify...
//
// struct clu_jxi488_cycle_args {
// int jxi488;
// ScattererConfiguration *sconf;
// GeometryConfiguration *gconf;
// C1 *c1;
// C1_AddOns *c1ao;
// C2 *c2;
// C3 *c3;
// C4 *c4;
// C6 *c6;
// C9 *c9;
// FILE *output;
// string output_path;
// double *gaps;
// double **tqse;
// dcomplex **tqspe;
// double **tqss;
// dcomplex **tqsps;
// double ****zpv;
// double **gapm;
// dcomplex **gappm;
// int nth, int nths;
// int nph;
// int nphs;
// int nk;
// int nks;
// int nkks;
// double *argi;
// double *args;
// double **gap;
// dcomplex **gapp;
// double **tqce;
// dcomplex **tqcpe;
// double **tqcs;
// dcomplex **tqcps;
// double *duk;
// fstream &tppoan;
// double **cextlr;
// double **cext;
// double **cmullr;
// double **cmul;
// double *gapv;
// double *tqev;
// double *tqsv;
// }
// I would like to put it all in a struct, but then I'd have to write a constructor for it, due to members defined as references, creating a worse nightmare than the one I'd like to simplify...
// To test parallelism, I will now start feeding this function with "clean" copies of the parameters, so that they will not be changed by previous iterations, and each one will behave as the first one
// Create and initialise this variable here, so that if OpenMP is enabled it is local to the thread, and if OpenMP is not enabled it has a well-defiled value anyway
intmyompthread=0;
#ifdef _OPENMP
// If OpenMP is enabled, give actual values to myompthread and ompnumthreads, and open thread-local output files
// If OpenMP is not enabled, just keep doing the output to the global files
FILE*output_2=output;
fstream&tppoan_2=tppoan;
#endif
double*gaps_2=newdouble[nsph]();
double**tqse_2=newdouble*[2];
double**tqce_2=newdouble*[2];
double**tqcs_2=newdouble*[2];
dcomplex**tqspe_2=newdcomplex*[2];
dcomplex**tqcpe_2=newdcomplex*[2];
dcomplex**tqcps_2=newdcomplex*[2];
double**tqss_2=newdouble*[2];
dcomplex**tqsps_2=newdcomplex*[2];
// To test parallelism, I will now start feeding this function with "clean" copies of the parameters, so that they will not be changed by previous iterations, and each one will behave as the first one. Define all (empty) variables here, so they have the correct scope, then they get different definitions depending on thread number
ScattererConfiguration*sconf_2=NULL;
GeometryConfiguration*gconf_2=NULL;
C1*c1_2=NULL;
C1_AddOns*c1ao_2=NULL;
C2*c2_2=NULL;
C3*c3_2=NULL;
C4*c4_2=NULL;
C6*c6_2=NULL;
C9*c9_2=NULL;
FILE*output_2=NULL;
fstream*tppoanp_2=NULL;
double*gaps_2=NULL;
double**tqse_2=NULL;
double**tqce_2=NULL;
double**tqcs_2=NULL;
dcomplex**tqspe_2=NULL;
dcomplex**tqcpe_2=NULL;
dcomplex**tqcps_2=NULL;
double**tqss_2=NULL;
dcomplex**tqsps_2=NULL;
double****zpv_2=NULL;
double**gapm_2=NULL;
dcomplex**gappm_2=NULL;
double**gap_2=NULL;
dcomplex**gapp_2=NULL;
double*argi_2=NULL;
double*args_2=NULL;
double*duk_2=NULL;
double**cextlr_2=NULL;
double**cext_2=NULL;
double**cmullr_2=NULL;
double**cmul_2=NULL;
double*gapv_2=NULL;
double*tqev_2=NULL;
double*tqsv_2=NULL;
intnxi_2=nxi;
intnsph_2=nsph;
np_intmxndm_2=mxndm;
intinpol_2=inpol;
intiavm_2=iavm;
intnpnt_2=npnt;
intnpntts_2=npntts;
intisam_2=isam;
intlm_2=lm;
doubleth_2=th;
doublethstp_2=thstp;
doublethlst_2=thlst;
doubleths_2=ths;
doublethsstp_2=thsstp;
doublethslst_2=thslst;
doubleph_2=ph;
doublephstp_2=phstp;
doublephlst_2=phlst;
doublephs_2=phs;
doublephsstp_2=phsstp;
doublephslst_2=phslst;
doubleth1_2=th1;
doubleph1_2=ph1;
doubleths1_2=ths1;
doublephs1_2=phs1;
doublethsca_2=thsca;
double*u_2=NULL;
double*us_2=NULL;
double*un_2=NULL;
double*uns_2=NULL;
double*up_2=NULL;
double*ups_2=NULL;
double*unmp_2=NULL;
double*unsmp_2=NULL;
double*upmp_2=NULL;
double*upsmp_2=NULL;
doublescan_2=scan;
doublecfmp_2=cfmp;
doublesfmp_2=sfmp;
doublecfsp_2=cfsp;
doublesfsp_2=sfsp;
doublesqsfi_2=sqsfi;
doubleexri_2=exri;
intlcalc_2=lcalc;
dcomplexarg_2=arg;
doublewn_2=wn;
doublevk_2=vk;
np_intndit_2=ndit;
dcomplex**am_2=NULL;
dcomplex*am_vector_2=NULL;
intisq_2=isq;
intibf_2=ibf;
intnth_2=nth;
intnths_2=nths;
intnph_2=nph;
intnphs_2=nph;
intnk_2=nk;
intnks_2=nks;
intnkks_2=nkks;
// for threads other than the 0, create distinct copies of all relevant data, while for thread 0 just define new references / pointers to the original ones
if(myompthread==0){
sconf_2=sconf;
gconf_2=gconf;
c1_2=c1;
c1ao_2=c1ao;
c2_2=c2;
c3_2=c3;
c4_2=c4;
c6_2=c6;
c9_2=c9;
output_2=output;
tppoanp_2=tppoanp;
gaps_2=gaps;
tqse_2=tqse;
tqce_2=tqce;
tqcs_2=tqcs;
tqspe_2=tqspe;
tqcpe_2=tqcpe;
tqcps_2=tqcps;
tqss_2=tqss;
tqsps_2=tqsps;
zpv_2=zpv;
gapm_2=gapm;
gappm_2=gappm;
gap_2=gap;
gapp_2=gapp;
argi_2=argi;
args_2=args;
duk_2=duk;
cextlr_2=cextlr;
cext_2=cext;
cmullr_2=cmullr;
cmul_2=cmul;
gapv_2=gapv;
tqev_2=tqev;
tqsv_2=tqsv;
u_2=u;
us_2=us;
un_2=un;
uns_2=uns;
up_2=up;
ups_2=ups;
unmp_2=unmp;
unsmp_2=unsmp;
upmp_2=upmp;
upsmp_2=upsmp;
am_2=am;
}
else{
// this is not thread 0, so do create fresh copies of all local variables
// make sure all threads align here: I don't want the following loop to accidentally start for thread 0, possibly modifying some variables before they are copied by all other threads
#pragma omp barrier
if(myompthread==0)printf("Syncing OpenMP threads and starting the loop on wavelengths\n");
// ok, now I can actually start the parallel calculations
printf("Closed thread-local output files of thread %d, syncing threads\n",myompthread);
}
}// closes pragma omp parallel
#ifdef _OPENMP
#pragma omp barrier
{
for(intri=0;ri<ompnumthreads;ri++){
// thread 0 already wrote on global files, skip it and take care of appending the others
for(intri=1;ri<ompnumthreads;ri++){
// Giovanni, please add here in this loop code to reopen the temporary files, reread them and append them respectively to the global output and tppoan, before closing them