/* Copyright 2008 BORDEAUX I UNIVERSITY & INRIA 
**
** This file is part of the PaStiX parallel sparse matrix package.
**
** This software is governed by the CeCILL-C license under French law
** and abiding by the rules of distribution of free software. You can
** use, modify and/or redistribute the software under the terms of the
** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
** URL: "http://www.cecill.info".
** 
** As a counterpart to the access to the source code and rights to copy,
** modify and redistribute granted by the license, users are provided
** only with a limited warranty and the software's author, the holder of
** the economic rights, and the successive licensors have only limited
** liability.
** 
** In this respect, the user's attention is drawn to the risks associated
** with loading, using, modifying and/or developing or reproducing the
** software by the user in light of its specific status of free software,
** that may mean that it is complicated to manipulate, and that also
** therefore means that it is reserved for developers and experienced
** professionals having in-depth computer knowledge. Users are therefore
** encouraged to load and test the software's suitability as regards
** their requirements in conditions enabling the security of their
** systems and/or data to be ensured and, more generally, to use and
** operate it in the same conditions as regards security.
** 
** The fact that you are presently reading this means that you have had
** knowledge of the CeCILL-C license and that you accept its terms.
*/
/* File: algotech.c
 *
 *  Executable written to solve several systems of the form (A + B * omega + C / omega) x = b
 *
 */

#define MIN(a,b) ((a<b)?a:b)
#define MAX(a,b) ((a>b)?a:b)

#include <stdint.h>
#include <stdlib.h> 
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>

#ifdef _OPENMP
#include <omp.h>
#endif

#ifndef FORCE_NOMPI
#include <mpi.h>
#  define START_TIMER(t1) do {                                          \
    gettimeofday(&tv, NULL);                                            \
    t1 = ((double) tv.tv_sec + (double) tv.tv_usec * (double)1.0e-6L);  \
  } while(0)

#  define STOP_TIMER(str, t1) do {                                      \
    double STOP_TIMER_t;                                                \
    gettimeofday(&tv, NULL);                                            \
    STOP_TIMER_t = ((double) tv.tv_sec +                                \
                    (double) tv.tv_usec * (double)1.0e-6L);             \
    fprintf(stdout, "%d $$ time for '%-40s' %.2e s $$\n", mpid, str,    \
            STOP_TIMER_t-t1);                                           \
  } while(0)
	  
#else
#  define START_TIMER(t1) do {                                          \
    gettimeofday(&tv, NULL);                                            \
    t1 = ((double) tv.tv_sec + (double) tv.tv_usec * (double)1.0e-6L);  \
  } while(0)

#  define STOP_TIMER(str, t1) do {                                      \
    double STOP_TIMER_t;                                                \
	FILE *ftimer;                                                		\
	gettimeofday(&tv, NULL);                                            \
    STOP_TIMER_t = ((double) tv.tv_sec +                                \
                    (double) tv.tv_usec * (double)1.0e-6L);             \
	ftimer = fopen("timer.txt","a+");									\
	fprintf(ftimer, " $$ time for '%-40s' %.2e s $$\n", str,            \
            STOP_TIMER_t-t1);											\
	fclose(ftimer);														\
	} while(0)

	  
#endif
#define PASTIX_HAS_COMPLEX
#define DEBUG 0
#include <complex.h>
/* to access functions from the libpastix, respect this order */
#include "pastix.h"
#include "cscd_utils.h"
#include "utils.h"
#include <assert.h>
extern char *optarg;
extern int optind, optopt;
#ifdef FORCE_NOMPI
#define MPI_COMM_WORLD 0
#define MPI_COMM_SELF  0
#endif

int debug = 0;
  
enum ERRORS {
  NO_ERROR                = 0,
  MATRIX_READ_ERROR       = 2,
  MATRIX_DIMENSIONS_ERROR = 3,
  MATRIX_SHAPE_ERROR      = 4,
  MEMORY_ERROR            = 6,
  MATRIX_CHECK_ERROR      = 7,
  SOLUTION_WRITE_ERROR    = 8,
  COMMAND_LINE_ERROR      = 9,
  PREPROCESSING_ERROR     = 10,
  FACTORSOLVE_ERROR       = 11,
  INPUTFILEREAD_ERROR     = 12,
  HOOK_UP_FILE_ERROR	  = 13
};

int alloc_read_file_int(FILE			*f,
					    pastix_int_t	**Tab,
					    pastix_int_t	*N,
						char 			*name1,
						int 			id1)
{  
		/*---allocation de la mémoire---*/
		if (NULL == (*Tab = malloc(*N*sizeof(pastix_int_t))))
		return MEMORY_ERROR;

		/*---lecture du fichier---*/  
		if (*N != fread(*Tab, sizeof(pastix_int_t), *N, f)) 
		  {
			fprintf(stderr, "ERROR: reading %s %d %d: Tab\n", name1,*N,id1);
			return HOOK_UP_FILE_ERROR;
		  }

	  return NO_ERROR;	  
}

int alloc_file_int2(FILE		    	*f,
					   pastix_int_t    	***Tab,
					   pastix_int_t		*N)
{
		/*---allocation de la mémoire---*/
		if (NULL == (**Tab = malloc((*N)*sizeof(pastix_int_t*))))
		return MEMORY_ERROR;
	
	 return NO_ERROR;
}


int alloc_read_file_double(FILE				*f,
						   double			**Tab,
					       pastix_int_t		*N,
						   int 				i,
						   char 			*name1,
						   int 				id1)
{
		/*---allocation de la mémoire---*/
		if (NULL == (*Tab = malloc(*N*sizeof(double))))
		return MEMORY_ERROR;

	if (i==1)
	{
		/*---lecture du fichier---*/  		  
		if (*N != fread(*Tab, sizeof(double), *N, f)) 
		{
			fprintf(stderr, "ERROR: reading %s %d : colptr\n", name1, id1);
			return HOOK_UP_FILE_ERROR;
		}
	}		

	 return NO_ERROR;
}

int alloc_file_double2(double    		*(**Tab),
					   pastix_int_t		*N)
{
		/*---allocation de la mémoire---*/
		if (NULL == (**Tab = malloc(*N*sizeof(double*))))
		return MEMORY_ERROR;
	
	 return NO_ERROR;
}

int alloc_file_double3(FILE		    	*f,
					   double    		****Tab,
					   pastix_int_t		*N)
{
		/*---allocation de la mémoire---*/
		if (NULL == (***Tab = malloc(*N*sizeof(double**))))
		return MEMORY_ERROR;
	
	 return NO_ERROR;
}
int memory_allocation2(pastix_int_t   *New_sizecolptr,
					  pastix_int_t   **colptr,								
					  double         **values)
{
	if (NULL == (*colptr = calloc((*New_sizecolptr),sizeof(pastix_int_t))))
			{
				return MEMORY_ERROR;
			}		

	if (NULL == (*values = calloc((*New_sizecolptr),sizeof(double))))
			{
				return MEMORY_ERROR;
			}	
		
	return NO_ERROR;

}

int memory_allocation(int 			 i ,
					  pastix_int_t   *New_sizecolptr,
					  pastix_int_t   **colptr,								
					  double         **values)
{
	pastix_int_t *colptr_realloc;
	
	/* Ré-Allocation de mémoire sans initialisation---*/
	if (i==1)
	{
	double *values_realloc;		
		colptr_realloc = realloc(*colptr,(*New_sizecolptr)*sizeof(pastix_int_t));
		if (colptr_realloc !=NULL)
		{
			*colptr = colptr_realloc;
		}
		else
		{
			return MEMORY_ERROR;
		}

		values_realloc = realloc(*values,(*New_sizecolptr)*sizeof(double));
		if (values_realloc !=NULL)
		{
			*values = values_realloc;
		}
		else
		{
			return MEMORY_ERROR;
		}		
	}
	/* Ré-Allocation de mémoire avec initialisation à 0---*/
	else 
	{
		colptr_realloc = realloc(*colptr,((*New_sizecolptr)+1)*sizeof(pastix_int_t));
		if (colptr_realloc !=NULL)
		{
			*colptr = colptr_realloc;
		}
		else
		{
			return MEMORY_ERROR;
		}		
	}
	
	return NO_ERROR;

}

void Inserer_valeur_CRS(int R,
						int C,
						int id1,
						double  	     val,
						pastix_int_t    *sizecolptr,						
						pastix_int_t   **colptr,				
						pastix_int_t   **rows,				
						double         **values,
						pastix_int_t   **Ligne)
{
	int i,j,k,m = 0;
	FILE 	*ff1 = NULL;
	//int debug1 = 1;
	
	if (debug == 1)
	{
		if ((id1>=-1) && (id1<=3)) {ff1 = fopen("Resistance", "a");}
		if ((id1>=9) && (id1<=12)) {ff1 = fopen("Resistance", "a");}
		if ((id1>=4) && (id1<=6))  {ff1 = fopen("Inductance", "a");}
		if (id1==-2)  {ff1 = fopen("Inductance", "a");}		
		if ((id1>=7) && (id1<=8)) {ff1 = fopen("Capacite", "a");}
		if (id1>=13) {ff1 = fopen("Capacite", "a");}
		if (id1==-3)  {ff1 = fopen("Capacite", "a");}
	}
	
	m = (*rows)[R-1]-1;
	
	if (debug == 1)
	{	
		fprintf(ff1,"*******************************\n");
		fprintf(ff1,"m = %d (*Ligne)[%d] = %d\n",m,R-1,(*Ligne)[R-1]);
		fprintf(ff1,"*******************************\n");
		for(i=m; i<(m + (*Ligne)[R-1]);i++)
		{
			fprintf(ff1,"    (*colptr)[%d]= %d\n",i,(*colptr)[i]);
		}
		fprintf(ff1,"*******************************\n");
	}
	
	k=-1;
	if ((*colptr)[m] != 0)
	{
		if (C==(*colptr)[m])
		{
			(*values)[m]+= val;
			k = m;
		}
		else if (C<(*colptr)[m])
		{
			for (j=(m + (*Ligne)[R-1] - 1);j>m;j--)
						{
							(*colptr)[j] = (*colptr)[j-1];
							(*values)[j] = (*values)[j-1];
						}
			k = m;
			(*colptr)[m] = C;
			(*values)[m] = val;
			
			if (debug == 1)
			{			
				fprintf(ff1,"***************NEW*************\n");
				for(j=m; j<(m + (*Ligne)[R-1]);j++)
				{
					fprintf(ff1,"    (*colptr)[%d]= %d\n",j,(*colptr)[j]);
				}
				fprintf(ff1,"***************NEW*************\n");			
			}
		}	
		else
		{
			i = m + 1 ;
			while(i<(m + (*Ligne)[R-1]))
			{
				if ((*colptr)[i]!=0)
				{
					if (C==(*colptr)[i])
					{
						(*values)[i]+= val;
						k = i;
						i =(m + (*Ligne)[R-1]);
					}
					else if (C<(*colptr)[i])
					{
						for (j=(m + (*Ligne)[R-1] - 1);j>i;j--)
						{
							(*colptr)[j] = (*colptr)[j-1];
							(*values)[j] = (*values)[j-1];
						}
						k = i;
						(*colptr)[i] = C;
						(*values)[i] = val;
						if (debug == 1)
						{						
							fprintf(ff1,"***************NEW*************\n");
							for(j=m; j<(m + (*Ligne)[R-1]);j++)
							{
								fprintf(ff1,"    (*colptr)[%d]= %d\n",j,(*colptr)[j]);
							}
							fprintf(ff1,"***************NEW*************\n");
						}
						i =(m + (*Ligne)[R-1]);						
					}
					else
					{
						i++;
					}
				}
				else
				{
					(*colptr)[i] = C;
					(*values)[i] = val;
					k = i;
					i =(m + (*Ligne)[R-1]);						
				}
			}
		}
	}
	else
	{
		(*colptr)[m] = C;
		(*values)[m] = val;
		k = m;		
	}
	if (debug == 1)
	{		
		if (k==-1) 
		{
			for(i=m; i<(m + (*Ligne)[R-1]);i++)
			{
				fprintf(ff1,"erreur id1 = %d (*Ligne)[%d] = %d (*colptr)[%d]= %d R=%d C= %d\n",id1,(R-1),(*Ligne)[R-1],i,(*colptr)[i],R,C);
			}
		}
		else
		{
			fprintf(ff1,"id1 = %d (*Ligne)[%d] = %d (*colptr)[%d]= %d (*rows)[%d] = %d R=%d C= %d\n",id1,(R-1),(*Ligne)[R-1],k,(*colptr)[k],(R-1),(*rows)[R-1],R,C);
		}
		fclose(ff1);
	}
}
int verif(pastix_int_t       R,
		  pastix_int_t       C,
		  pastix_int_t   **colptr,
		  pastix_int_t   **rows,
		  pastix_int_t	 **Ligne)
{
	int m;
	if ((*Ligne)[R-1]==0)
	{
		return 0;
	}
	else
	{
		m = (*rows)[R-1]-1;
		while (m<((*rows)[R-1] + (*Ligne)[R-1]-1))
		{
			if (C==(*colptr)[m])
			{
				return 1;
			}
			else
			{
				m++;
			}
		}
	}
	return 0;
}

int taille_values_maj_rows( pastix_int_t       R,
							pastix_int_t       R22,
							pastix_int_t       posource,
							pastix_int_t       NbToron,
							pastix_int_t       Nligne,
							pastix_int_t      *Nbfils,
							pastix_int_t      *NbCellule,
							pastix_int_t     **LigneRes,
							pastix_int_t     **LigneInd,
							pastix_int_t     **LigneCap,						
							pastix_int_t     **ConnectionRes,
							pastix_int_t     **ConnectionInd,
							pastix_int_t     **Filsblindee,
							pastix_int_t    ***couple,
							pastix_int_t      *New_sizecolptrres,
							pastix_int_t   	  *New_sizecolptrind,
							pastix_int_t      *New_sizecolptrcap,
							pastix_int_t  *****Tabposition,
							pastix_int_t   **colptrcon,
							pastix_int_t   **colptrcap,
							pastix_int_t   **colptrind,				
							pastix_int_t   **rowscon,
							pastix_int_t   **rowscap,
							pastix_int_t   **rowsind,
							double         ***valCapBlind,
							double         ***valCap,
							double 		   ***valind,
							double 		   ***valcon,
							double 		   ****valmut1,
							double 		   ****valmut2,
							double 		   ****valmut12,
							double 		   ****valsCap)
{
	int 	total,i,j,k,k1,sort,l,R3 = posource,R1,R4,R5,R6,R7,R8,R2=R22,R9 = 0,F,F1,max1;//R4,R5,
	FILE 	*ff1 = NULL,*ff2 = NULL,*ff3 = NULL;
	FILE 	*ff4 = NULL,*ff5 = NULL,*ff6 = NULL;
	
	if (debug == 1) 
	{
		ff1 = fopen("Connectionres", "w+");
		ff2 = fopen("Connectionind", "w+");		
		for (i = 0; i<NbToron ; i++)
		{
			fprintf(ff1,"\n**********************\n i= %d \n**********************\n",i);
			fprintf(ff2,"\n**********************\n i= %d \n**********************\n",i);
			for(j=0;j<Nbfils[i];j++)
			{
				fprintf(ff1," j = %d C1 = %d C2 = %d\n",j,ConnectionRes[i][2*j],ConnectionRes[i][(2*j)+1]);
				fprintf(ff2," j = %d C1 = %d C2 = %d\n",j,ConnectionInd[i][2*j],ConnectionInd[i][(2*j)+1]);
			}
		}
		fclose(ff1);
		fclose(ff2);
	}
	
	if (debug == 1)
	{	
		ff1 = fopen("Res1", "w+");
		ff2 = fopen("Ind1", "w+");
		ff3 = fopen("Cap1", "w+");
		ff4 = fopen("Res_L", "w+");
		ff5 = fopen("Ind_L", "w+");
		ff6 = fopen("Cap_L", "w+");		
	}
	
	max1 = R2;	
	R1 = MIN(ConnectionRes[0][0],ConnectionRes[0][1]);
	
	R5 = 0;
	R6 = 0;
	R7 = 0;
	R8 = 0;


	for (i = 0; i<NbToron ; i++)
	{
		if (debug == 1) 
		{
			fprintf(ff1,"\n*************\n Resistance\n*************\n");
			fprintf(ff2,"\n*************\n Inductance\n*************\n");
			fprintf(ff3,"\n*************\n Capacitance\n*************\n");
			fprintf(ff1,"\n******\n max1 = %d \n******\n",max1);
		}		
		for(j=0;j<Nbfils[i];j++)
		{
			F1 = 0;
			R4 = -1;
			
			if (ConnectionRes[i][2*j]<R)
			{
				F1 = 1;
				R4 = 2;
				R1 = ConnectionRes[i][2*j];
			}				
			else if (ConnectionRes[i][(2*j)+1]<R)
			{
				F1 = 1;
				R4 = 2;
				R1 = ConnectionRes[i][(2*j)+1];
			}
			else
			{				
				k = 0;
				while (k<NbToron)
				{
					if (k!=i)
					{
						k1 = 0 ;
						sort = 0;
						while (sort!= 1)
						{
							if (k1<(Nbfils[k]))
							{
								if (ConnectionRes[i][2*j]==ConnectionInd[k][2*k1]) 
								{
									R1 = ConnectionRes[i][2*j];
									R4 = 1;
									k1 = -1;
								}
								else if(ConnectionRes[i][2*j]==ConnectionInd[k][(2*k1)+1])
								{
									R1 = ConnectionRes[i][2*j];
									R4 = 1;
									k1 = -1;
								}							
								else if (ConnectionRes[i][(2*j)+1]==ConnectionInd[k][(2*k1)+1])
								{
									R1 = ConnectionRes[i][(2*j)+1];
									R4 = 1;
									k1 = -1;
								}							
								else if (ConnectionRes[i][(2*j)+1]==ConnectionInd[k][2*k1])
								{
									R1 = ConnectionRes[i][(2*j)+1];
									R4 = 1;
									k1 = -1;
								}
								else						
								{
									k1++;
								}
								
								if (k1==-1)
								{
									sort= 1;
								}
								else
								{
									sort= 0;
								}							
							}
							else
							{
								sort = 1;
							}
						}
						if (k1==-1)
						{
							k = NbToron ;
						}
						else
						{
							k++;
						}
					}
					else
					{
						k++;
					}
				}
			}

			F = 0;

			if ((ConnectionInd[i][2*j]<R) || (ConnectionInd[i][(2*j)+1]<R))
			{
				F = 1;
			}
			
			if (debug == 1) 
			{
				fprintf(ff1,"*************************\n");
				//fprintf(ff1," i = %d  R4 = %d F = %d F1 = %d j = %d R1 = %d  R2 = %d \n",i,R4,F,F1,j,R1,R2);
				fprintf(ff1," j = %d R1 = %d  R2 = %d \n",j,R1,R2);
				fprintf(ff1,"*************************\n");
			
				fprintf(ff2,"*************************\n");
				//fprintf(ff2," i = %d j = %d R1 = %d  R2 = %d \n",i,j,R1,R2);
				fprintf(ff2," j = %d R1 = %d  R2 = %d \n",j,R1,R2);
				fprintf(ff2,"*************************\n");

				fprintf(ff3,"*************************\n");
				//fprintf(ff3," i = %d j = %d R1 = %d  R2 = %d \n",i,j,R1,R2);
				fprintf(ff3," j = %d R1 = %d  R2 = %d \n",j,R1,R2);
				fprintf(ff3,"*************************\n");			
				
				//printf("\n************\n Fils j = %d \n************\n",j);	
			}
					
			
			/***************************************/
			/*									   */
			/*     détermination de la position    */
			/*		 de chaque entrée dans         */
			/*	    les lignes de la matrice       */
			/*									   */
			/***************************************/				
						
			for (k=0;k<NbCellule[i];k++)
			{
				R8 = MAX(R8,R2);
				if ((k==NbCellule[i]-1)) //&& (F==1)) 
				{
					//R4 = -1;
					//R2 = MAX(ConnectionInd[i][2*j],ConnectionInd[i][(2*j)+1]);
					if (ConnectionInd[i][2*j]==ConnectionRes[i][2*j])
					{
						R2 = ConnectionInd[i][2*j];
					}
					else if (ConnectionInd[i][2*j]==ConnectionRes[i][(2*j)+1])
					{
						R2 = ConnectionInd[i][2*j];
					}
					else if (ConnectionInd[i][(2*j)+1]==ConnectionRes[i][2*j])
					{
						R2 = ConnectionInd[i][(2*j)+1];
					}
					else
					{
						R2 = ConnectionInd[i][(2*j)+1];
					}
					
				}
				
				if ((k==0) && (k!=NbCellule[i]-1))
				{
					if (R2<R8)
					{
						R2 = R8;
						//R4 = 0;
					}
				}
				
				if (debug == 1) 
				{
					fprintf(ff1,"*********\n");
					fprintf(ff1," R8 = %d \n",R8);
					fprintf(ff1,"*********\n");
				}				
				
				//Matrice Résistance
				//R1,R1
				if (verif(R1,R1,colptrcon,rowscon,LigneRes)==0)
				{
					(*LigneRes)[R1-1]++;
					
					if (debug == 1) 
					{
						fprintf(ff4," (*LigneRes)[R1-1] = %d R1 = %d R1 = %d\n",(*LigneRes)[R1-1],R1,R1);
					}					
				}
				if (debug == 1)
				{
					fprintf(ff1,"R1 = %d R1 = %d val = %10.10f\n",R1,R1,(*valcon)[i][j]);
				}						
				//R1,R2 ou R2/R1
				if (R2<R1)
				{							
					if (debug == 1)
					{								
						fprintf(ff1,"R1 = %d R2 = %d val = %10.10f\n",R1,R2,(-1.0)*(*valcon)[i][j]);
					}							
					if (verif(R1,R2,colptrcon,rowscon,LigneRes)==0)
					{
						(*LigneRes)[R1-1]++;
						if (debug == 1) 
						{
							fprintf(ff4," (*LigneRes)[R1-1] = %d R1 = %d R2 = %d\n",(*LigneRes)[R1-1],R1,R2);
						}
					}				
				}
				else
				{
					if (debug == 1)
					{							
						fprintf(ff1,"R2 = %d R1 = %d val = %10.10f\n",R2,R1,(-1.0)*(*valcon)[i][j]);
					}
					if (verif(R2,R1,colptrcon,rowscon,LigneRes)==0)
					{
						(*LigneRes)[R2-1]++;
						if (debug == 1) 
						{
							fprintf(ff4," (*LigneRes)[R2-1] = %d R2 = %d R1 = %d\n",(*LigneRes)[R2-1],R2,R1);
						}
					}
				}
				
				if (debug == 1)
				{				
					fprintf(ff1,"R2 = %d R2 = %d val = %10.10f\n",R2,R2,(*valcon)[i][j]);
				}
				//R2,R2
				if (verif(R2,R2,colptrcon,rowscon,LigneRes)==0)
				{
					(*LigneRes)[R2-1]++;
					if (debug == 1) 
					{
						fprintf(ff4," (*LigneRes)[R2-1] = %d R2 = %d R2 = %d\n",(*LigneRes)[R2-1],R2,R2);
					}
				}				
				
				(*Tabposition)[i][j][k][0] = R1;
				(*Tabposition)[i][j][k][1] = R2;
				
				R1 = R2;
				R2++;
				R9 = R2;
				//Matrice Inductance et Capacité
				if (k == NbCellule[i]-1) 
				{
					//if (F==1)
					//{
					//	R2 = MIN(ConnectionInd[i][2*j],ConnectionInd[i][(2*j)+1]);												
					//}
					if (ConnectionInd[i][2*j]==ConnectionRes[i][2*j])
					{
						R2 = ConnectionInd[i][(2*j)+1];
					}
					else if (ConnectionInd[i][2*j]==ConnectionRes[i][(2*j)+1])
					{
						R2 = ConnectionInd[i][(2*j)+1];
					}
					else if (ConnectionInd[i][(2*j)+1]==ConnectionRes[i][2*j])
					{
						R2 = ConnectionInd[i][(2*j)];
					}
					else
					{
						R2 = ConnectionInd[i][(2*j)];
					}
				}
				
				//R1,R2 ou R2/R1
				if (R2<R1)
				{
					if (debug == 1)
					{							
						fprintf(ff2,"R1 = %d R2 = %d val = %10.10f\n",R1,R2,(-1.0)*(*valind)[i][j]);
					}
					if (verif(R1,R2,colptrind,rowsind,LigneInd)==0)
					{
						(*LigneInd)[R1-1]++;
						if (debug == 1) 
						{
							fprintf(ff5," (*LigneInd)[R1-1] = %d R1 = %d R2 = %d\n",(*LigneInd)[R1-1],R1,R2);
						}
					}							
				}
				else
				{
					if (debug == 1)
					{									
						fprintf(ff2,"R2 = %d R1 = %d val = %10.10f\n",R2,R1,(-1.0)*(*valind)[i][j]);
					}							
					if (verif(R2,R1,colptrind,rowsind,LigneInd)==0)
					{
						(*LigneInd)[R2-1]++;
						
						if (debug == 1) 
						{
							fprintf(ff5," (*LigneInd)[R2-1] = %d R2 = %d R1 = %d\n",(*LigneInd)[R2-1],R2,R1);
						}
					}							
				}
				
				if (k == NbCellule[i]-1) 
				{				
					if (F==1)
					{
						if (Filsblindee[i][j] == 1) 
						{
							if (debug == 1)
							{							
								fprintf(ff3,"Blindée R8+1 = %d R2 = %d val = %10.10E\n",R8+1,R2,(-1.0)*(*valCapBlind)[i][j]);
								fprintf(ff3,"Blindée R8+1 = %d R8+1 = %d val = %10.10E\n",R8+1,R8+1,(*valCapBlind)[i][j]);
							}
							if (verif(R8+1,R2,colptrcap,rowscap,LigneCap)==0)
							{
								(*LigneCap)[R8]++;
								
								if (debug == 1) 
								{
									fprintf(ff6," (*LigneCap)[R8] = %d R8+1 = %d R2 = %d\n",(*LigneCap)[R8] ,R8+1,R2);
								}
							}
							if (verif(R8+1,R8+1,colptrcap,rowscap,LigneCap)==0)
							{
								(*LigneCap)[R8]++;
								if (debug == 1) 
								{
									fprintf(ff6," (*LigneCap)[R8] = %d R8+1 = %d R8+1 = %d\n",(*LigneCap)[R8],R8+1,R8+1);
								}
							}							
							(*Tabposition)[i][j][k][5] = R8 + 1;
						}
						else
						{
							if (debug == 1)
							{								
								fprintf(ff3,"R2 = %d R2 = %d val = %10.10E\n",R2,R2, (*valCap)[i][j]);
							}
							if (verif(R2,R2,colptrcap,rowscap,LigneCap)==0)
							{
								(*LigneCap)[R2-1]++;
								
								if (debug == 1) 
								{
									fprintf(ff6," (*LigneCap)[R2-1] = %d R2 = %d R2 = %d\n",(*LigneCap)[R2-1],R2,R2);
								}
							}
						}
					}
					else
					{
						if (Filsblindee[i][j] == 1) 
						{
							if (debug == 1)
							{							
								fprintf(ff3,"Blindée R8+1 = %d R2 = %d val = %10.10E\n",R8+1,R2,(-1.0)*(*valCapBlind)[i][j]);
								fprintf(ff3,"Blindée R8+1 = %d R8+1 = %d val = %10.10E\n",R8+1,R8+1,(*valCapBlind)[i][j]);
							}
							if (verif(R2+1,R2,colptrcap,rowscap,LigneCap)==0)
							{
								(*LigneCap)[R2]++;
								
								if (debug == 1) 
								{
									fprintf(ff6," (*LigneCap)[R2] = %d R2+1 = %d R2 = %d\n",(*LigneCap)[R2],R2+1,R2);
								}
							}
							if (verif(R2+1,R2+1,colptrcap,rowscap,LigneCap)==0)
							{
								(*LigneCap)[R2]++;
								
								if (debug == 1) 
								{
									fprintf(ff6," (*LigneCap)[R2] = %d R2+1 = %d R2+1 = %d\n",(*LigneCap)[R2],R2+1,R2+1);
								}
							}							
							(*Tabposition)[i][j][k][5] = R2 + 1;
						}
						else
						{
							if (debug == 1)
							{								
								fprintf(ff3,"R2 = %d R2 = %d val = %10.10E\n",R2,R2, (*valCap)[i][j]);
							}
							if (verif(R2,R2,colptrcap,rowscap,LigneCap)==0)
							{
								(*LigneCap)[R2-1]++;
								
								if (debug == 1) 
								{
									fprintf(ff6," (*LigneCap)[R2-1] = %d R2 = %d R2 = %d\n",(*LigneCap)[R2-1],R2,R2);
								}
							}
						}
					}
				}
				else
				{
					if (Filsblindee[i][j] == 1) 
					{
						if (debug == 1)
						{							
							fprintf(ff3,"Blindée R8+1 = %d R2 = %d val = %10.10E\n",R8+1,R2,(-1.0)*(*valCapBlind)[i][j]);
							fprintf(ff3,"Blindée R8+1 = %d R8+1 = %d val = %10.10E\n",R8+1,R8+1,(*valCapBlind)[i][j]);
						}
						if (verif(R2+1,R2,colptrcap,rowscap,LigneCap)==0)
						{
							(*LigneCap)[R2]++;
							
							if (debug == 1) 
							{
								fprintf(ff6," (*LigneCap)[R2] = %d R2+1 = %d R2 = %d\n",(*LigneCap)[R2],R2+1,R2);
							}
						}
						if (verif(R2+1,R2+1,colptrcap,rowscap,LigneCap)==0)
						{
							(*LigneCap)[R2]++;
							
							if (debug == 1) 
							{
								fprintf(ff6," (*LigneCap)[R2] = %d  R2+1 = %d R2+1 = %d\n",(*LigneCap)[R2], R2+1,R2+1);
							}
						}							
						(*Tabposition)[i][j][k][5] = R2 + 1;
					}
					else
					{
						if (debug == 1)
						{								
							fprintf(ff3,"R2 = %d R2 = %d val = %10.10E\n",R2,R2, (*valCap)[i][j]);
						}
						if (verif(R2,R2,colptrcap,rowscap,LigneCap)==0)
						{
							(*LigneCap)[R2-1]++;
							
							if (debug == 1) 
							{
								fprintf(ff6," (*LigneCap)[R2-1] = %d R2 = %d R2 = %d\n",(*LigneCap)[R2-1],R2,R2);
							}
						}
					}
				}
						
					
					
				//R1,R1
				if (debug == 1)
				{						
					fprintf(ff2,"R1 = %d R1 = %d val = %10.10f\n",R1,R1,(*valind)[i][j]);
				}
				
				if (verif(R1,R1,colptrind,rowsind,LigneInd)==0)
				{
					(*LigneInd)[R1-1]++;
					
					if (debug == 1) 
					{
						fprintf(ff5," (*LigneInd)[R1-1] = %d R1 = %d R1 = %d\n",(*LigneInd)[R1-1],R1,R1);
					}
				}

				//R2,R2
				if (debug == 1)
				{							
					fprintf(ff2,"R2 = %d R2 = %d val = %10.10f\n",R2,R2,(*valind)[i][j]);
				}
				if (verif(R2,R2,colptrind,rowsind,LigneInd)==0)
				{
					(*LigneInd)[R2-1]++;
					
					if (debug == 1) 
					{
						fprintf(ff5," (*LigneInd)[R2-1] = %d R2 = %d R2 = %d\n",(*LigneInd)[R2-1],R2,R2);
					}
				}
				
				(*Tabposition)[i][j][k][2] = R1;
				(*Tabposition)[i][j][k][3] = R2;
				if (F != 1)
				{	
					if (Filsblindee[i][j] == 1) 
					{
						R2++;
					}			
					R1 = R2;
					R2++;
				}
				else
				{
					R2 = R9;
					if (Filsblindee[i][j] == 1) 
					{
						R2++;
					}			
					R1 = R2;
					R2++;					
				}
			}
		}
		
		if (debug == 1)
		{
			fprintf(ff1,"\n**********\n R3 = %d \n**********\n",posource);
			fprintf(ff2,"\n**********\n  R3 = %d \n**********\n",posource);
			fprintf(ff3,"\n**********\n  R3 = %d \n**********\n",posource);
		
			fprintf(ff1,"\n**********\n mutuelle\n**********\n");
			fprintf(ff2,"\n**********\n mutuelle\n**********\n");
			fprintf(ff3,"\n**********\n mutuelle\n**********\n");		
		}
		
		for(j=0;j<(Nbfils[i]-1);j++)
		{			
			for(k=j+1;k<Nbfils[i];k++)
			{
				if (couple[i][j][k]==1)
				{
					couple[i][j][k]= 2 ;
					couple[i][k][j]= 2 ;				

					for (l=0;l<NbCellule[i];l++)
					{
						if (debug == 1)			
						{
							fprintf(ff1,"\n**********************\n j = %d k = %d  l = %d \n**********************\n",j,k,l);
						}						
						R6 = (*Tabposition)[i][j][l][3];
						R7 = (*Tabposition)[i][k][l][3];
						
						if (debug == 1)
						{
							R4 = (*Tabposition)[i][j][l][2];
							fprintf(ff1,"R3 = %d R4 = %d val = %10.10f 5\n",R3,R4,(-1.0));
							fprintf(ff1,"R3 = %d R6 = %d val = %10.10f 5\n",R3,R6,(1.0));
							
							if ((i==0)&&(j==0)&&(k==1)&&(l==0))
							{
								printf("***************************\n");
								printf("i = %d j = %d k = %d l = %d\n",i,j,k,l);
								printf("***************************\n");
								//printf("R3 = %d R4 = %d\n",R3,R4);
								//printf("R3 = %d R6 = %d\n",R3,R6);
							}
						}
						//R3,R4 et R3,R6
						if (verif(R3,R4,colptrcon,rowscon,LigneRes)==0)
						{
							(*LigneRes)[R3-1]++;
							if (debug == 1) 
							{
								fprintf(ff4," (*LigneRes)[R3-1] = %d R3 = %d R4 = %d\n",(*LigneRes)[R2-1],R3,R4);
							}
							
						}
						if (verif(R3,R6,colptrcon,rowscon,LigneRes)==0)
						{
							(*LigneRes)[R3-1]++;
							
							if (debug == 1) 
							{
								fprintf(ff4," (*LigneRes)[R3-1] = %d R3 = %d R6 = %d\n",(*LigneRes)[R2-1],R3,R6);
							}
						}						
						
						if (debug == 1)
						{
							R5 = (*Tabposition)[i][k][l][2];
							fprintf(ff1,"(R3+1) = %d R5 = %d val = %10.10f 5\n",R3+1,R5,(-1.0));
							fprintf(ff1,"(R3+1) = %d R7 = %d val = %10.10f 5\n",R3+1,R7,(1.0));
							//printf("(R3+1) = %d R5 = %d\n",(R3+1),R5);
							//printf("(R3+1) = %d R7 = %d\n",(R3+1),R7);							
						}
						//R3+1,R5 et R3+1,R7
						if (verif(R3+1,R5,colptrcon,rowscon,LigneRes)==0)
						{						
							(*LigneRes)[R3]++;
							
							if (debug == 1) 
							{
								fprintf(ff4," (*LigneRes)[R3] = %d R3+1 = %d R5 = %d\n",(*LigneRes)[R3],R3+1,R5);
							}
						}
						if (verif(R3+1,R7,colptrcon,rowscon,LigneRes)==0)
						{						
							(*LigneRes)[R3]++;
							
							if (debug == 1) 
							{
								fprintf(ff4," (*LigneRes)[R3] = %d R3+1 = %d R7 = %d\n",(*LigneRes)[R3],R3+1,R7);
							}
						}
						
						if (debug == 1)
						{						
							fprintf(ff3,"R3 = %d R3 = %d val = %10.10E 1\n",R3,R3,(*valmut1)[i][j][k]);
							//printf("R3 = %d R3 = %d\n",R3,R3);							
						}
						
						//R3,R3
						if (verif(R3,R3,colptrcap,rowscap,LigneCap)==0)
						{
							(*LigneCap)[R3-1]++;
							
							if (debug == 1) 
							{
								fprintf(ff6," (LigneCap)[R3-1] = %d R3 = %d R3 = %d\n",(*LigneCap)[R3-1],R3,R3);
							}
						}
						
						if (debug == 1)
						{						
							fprintf(ff3,"(R3+1) = %d R3 = %d val = %10.10E 2\n",R3+1,R3, (*valmut12)[i][j][k]);
							fprintf(ff3,"(R3+1) = %d (R3+1) = %d val = %10.10E 3\n",R3+1,R3+1, (*valmut2)[i][j][k]);
							//printf("(R3+1) = %d R3 = %d\n",(R3+1),R3);
							//printf("(R3+1) = %d (R3+1) = %d\n",(R3+1),(R3+1));								
						}
						
						//R3+1,R3 et R3+1,R3+1
						if (verif(R3+1,R3,colptrcap,rowscap,LigneCap)==0)
						{
							(*LigneCap)[R3]++;
							
							if (debug == 1) 
							{
								fprintf(ff6," (LigneCap)[R3] = %d R3+1 = %d R3 = %d\n",(*LigneCap)[R3],R3+1,R3);
							}
						}
						
						if (verif(R3+1,R3+1,colptrcap,rowscap,LigneCap)==0)
						{
							(*LigneCap)[R3]++;
							
							if (debug == 1) 
							{
								fprintf(ff6," (LigneCap)[R3] = %d R3+1 = %d R3+1 = %d\n",(*LigneCap)[R3],R3+1,R3+1);
							}
						}						
						
						R3+=2;						
					}
					for (l=0;l<NbCellule[i];l++)
					{
						R6 = (*Tabposition)[i][j][l][3];
						R7 = (*Tabposition)[i][k][l][3];						
						
						//R6,R6 ou R7,R7
						if (debug == 1)
						{
							fprintf(ff3,"R6 = %d R6 = %d val = %10.10E 3\n",R6,R6, (*valsCap)[i][j][k]);
							fprintf(ff3,"R7 = %d R7 = %d val = %10.10E 4\n",R7,R7, (*valsCap)[i][j][k]);
						}
						
						//R6,R3 ou R7,R6
						if (R7<R6)
						{
							if (debug == 1)
							{							
								fprintf(ff3,"R6 = %d R7 = %d val = %10.10E 5\n",R6,R7,(-1.0)*(*valsCap)[i][j][k]);
							}
							if (verif(R6,R7,colptrcap,rowscap,LigneCap)==0)
							{
								(*LigneCap)[R6-1]++;
								
								if (debug == 1) 
								{
									fprintf(ff6," (LigneCap)[R6-1] = %d R6 = %d R7 = %d\n",(*LigneCap)[R6-1],R6,R7);
								}
							}							
						}
						else
						{
							if (debug == 1)
							{							
								fprintf(ff3,"R7 = %d R6 = %d val = %10.10E 6\n",R7,R6,(-1.0)*(*valsCap)[i][j][k]);
							}
							if (verif(R7,R6,colptrcap,rowscap,LigneCap)==0)
							{
								(*LigneCap)[R7-1]++;
								
								if (debug == 1) 
								{
									fprintf(ff6," (LigneCap)[R7-1] = %d R7 = %d R6 = %d\n",(*LigneCap)[R7-1],R7,R6);
								}
							}							
						}
					}
				}
			}				
		}
		/*if (debug == 1)
		{		
			fprintf(ff1,"*****************************\n");
			fprintf(ff1,"******** fin mutuelle *******\n");
			fprintf(ff1,"*****************************\n");

			fprintf(ff3,"*****************************\n");
			fprintf(ff3,"******** fin mutuelle *******\n");
			fprintf(ff3,"*****************************\n");	
		}*/			
	}
	
	*New_sizecolptrres = 0;
	*New_sizecolptrind = 0;
	*New_sizecolptrcap = 0;
	
	if (debug == 1)
	{
		fclose(ff1);
		fclose(ff3);
		fclose(ff2);
		
		fclose(ff4);
		fclose(ff5);
		fclose(ff6);
		
		ff1 = fopen("posRes1", "w+");
		ff2 = fopen("posInd1", "w+");
		ff3 = fopen("posCap1", "w+");

		fprintf(ff1,"R = %d\n",R);
		fprintf(ff1,"R2 = %d\n",R22);		
		fprintf(ff2,"R = %d\n",R);
		fprintf(ff2,"R2 = %d\n",R22);
		fprintf(ff3,"R = %d\n",R);
		fprintf(ff3,"R2 = %d\n",R22);		
	}
	
	total = 0 ;
	for (j=0;j<Nligne;j++)
	{
		*New_sizecolptrres += (*LigneRes)[j];
		*New_sizecolptrind += (*LigneInd)[j];
		*New_sizecolptrcap += (*LigneCap)[j];
		if (((*LigneRes)[j]!=0)||((*LigneInd)[j]!=0) ||((*LigneCap)[j]!=0)) 
		{
			total++;
		}
		if (debug == 1)
		{			
			fprintf(ff1,"(LigneRes)[%d] = %d\n",j,(*LigneRes)[j]);
			fprintf(ff2,"(LigneInd)[%d] = %d\n",j,(*LigneInd)[j]);
			fprintf(ff3,"(LigneCap)[%d] = %d\n",j,(*LigneCap)[j]);
		}	
	}
	
	if (debug == 1)
	{
		printf("Nbligne = %d\n",total);
		fprintf(ff1,"New_sizecolptrres = %d\n",*New_sizecolptrres);
		fprintf(ff2,"New_sizecolptrind = %d\n",*New_sizecolptrind);
		fprintf(ff3,"New_sizecolptrcap = %d\n",*New_sizecolptrcap);
	
		fclose(ff1);
		fclose(ff3);
		fclose(ff2);
	}
	
	return NO_ERROR;
}

int remplissage_matrice(pastix_int_t   *ncon,
						pastix_int_t   *ncap,				
						pastix_int_t   *nind,				
						pastix_int_t   **colptrcon,
						pastix_int_t   **colptrcap,
						pastix_int_t   **colptrind,				
						pastix_int_t   **rowscon,
						pastix_int_t   **rowscap,
						pastix_int_t   **rowsind,				
						double         **valuescon,
						double         **valuescap,				
						double         **valuesind)
{
	int 		   incon,i,j1,k,m,n,l,lmax,R,R1,R2,R3,R4,R5,R6,R7,R8,R9,max1;
	int 		   NbRes,NbInd,NbCap;
	int 		   ret;
	int 		   ****Tabposition;
	static int 	   id1 = 0;
	char 		   name1[]="Hook_up";
	pastix_int_t   ii,jj;
	pastix_int_t   j;
	pastix_int_t   Nbequipnsres; 
	pastix_int_t   Nbequipnsind; 
	pastix_int_t   Nbequipnscap;
	pastix_int_t   NbrAdd;	
	pastix_int_t   Nbrsource;
	pastix_int_t   PosSource; 
	pastix_int_t   NbToron; 
	pastix_int_t   Old_sizecolptrres; 
	pastix_int_t   Old_sizecolptrind; 
	pastix_int_t   Old_sizecolptrcap;
	pastix_int_t   New_sizecolptrres; 
	pastix_int_t   New_sizecolptrind; 
	pastix_int_t   New_sizecolptrcap;		
	pastix_int_t   *Nbfils;
	pastix_int_t   *LigneRes;
	pastix_int_t   *LigneInd;
	pastix_int_t   *LigneCap;	
	pastix_int_t   *NbCellule;
	pastix_int_t   *TabcolRes;
	pastix_int_t   *TabrowsRes;	
	pastix_int_t   *TabcolInd;
	pastix_int_t   *TabcolCap;	
	pastix_int_t   *TabrowsInd;
	pastix_int_t   *TabrowsCap;	
	pastix_int_t   **ConnectionRes;
	pastix_int_t   **ConnectionInd;	
	pastix_int_t   ***couple;
	pastix_int_t   **Filsblindee;
	double		   dd;
	double   	   *TabValuesRes;	
	double   	   *TabValuesInd;		
	double   	   *TabValuesCap;		
    double         **valCapBlind;
	double         **valCap;
    double 		   **valind;
    double 		   **valcon;	
	double 		   ***valmut1;
	double 		   ***valmut2;
	double 		   ***valmut12;
	double 		   ***valsCap;
	double 		   aux;
	FILE 			*ff1 = NULL,*ff2 = NULL,*ff3 = NULL,*f1 = NULL, *ff17= NULL;
/*******************************************/
/*										   */
/*   	  Lecture de la Hook_up            */
/*		 Récupération des données          */
/*	    Pour chaque fils des Torons        */
/*		 		Modélisés   		       */
/*										   */
/*******************************************/	
	

	if (debug == 1) 
	{
		fprintf(stderr," Début read_hook_up\n");
	}	
	  FILE *f = fopen(name1, "rb");
	  
	  if (f == NULL) {
		char error[1024];
		sprintf(error, "%s:%d:fopen %s", __FILE__, __LINE__, name1);
		perror(error);
		return HOOK_UP_FILE_ERROR;
	  }
/*----------------------------------------------*/	  
/*	lecture du nombre d'équipement non sources	*/
/*----------------------------------------------*/
	
	  /* Nombre d'équipement résisitance*/
	  id1 = 1;
	  n = fread(&Nbequipnsres, sizeof(pastix_int_t), 1, f);
	  if (n != 1) 
	  {
		fprintf(stderr, "ERROR: reading %s %d : n = %d\n", name1, id1,n);
		return HOOK_UP_FILE_ERROR;
	  }
	if (debug == 1) 
	{
		fprintf(stderr," Nbequipnsres = %d \n",Nbequipnsres);
	}	 	  

	  /* Nombre d'équipement inductance*/
	  id1 = 2;
	  if (1 != fread(&Nbequipnsind, sizeof(pastix_int_t), 1, f)) 
	  {
		fprintf(stderr, "ERROR: reading %s %d : n\n", name1, id1);
		return HOOK_UP_FILE_ERROR;
	  }
	if (debug == 1) 
	{
		fprintf(stderr,"Nbequipnsind = %d\n",Nbequipnsind);
	}	  
	  /* Nombre d'équipement capacité*/
	  id1 = 3;
	  if (1 != fread(&Nbequipnscap, sizeof(pastix_int_t), 1, f)) 
	  {
		fprintf(stderr, "ERROR: reading %s %d : n\n", name1, id1);
		return HOOK_UP_FILE_ERROR;
	  }
	if (debug == 1) 
	{
		fprintf(stderr,"Nbequipnscap = %d\n",Nbequipnscap);
	}
	  /* Nombre de ligne de décalage de la source*/
	  id1 = 3;
	  if (1 != fread(&NbrAdd, sizeof(pastix_int_t), 1, f)) 
	  {
		fprintf(stderr, "ERROR: reading %s %d : n\n", name1, id1);
		return HOOK_UP_FILE_ERROR;
	  }	  
/*------------------------------*/
/* lecture du nombre de sources	*/
/*------------------------------*/
	if (debug == 1) 
	{
		fprintf(stderr,"NbrAdd = %d \n",NbrAdd);
	}
	  id1 = 4;
	  if (1 != fread(&Nbrsource, sizeof(pastix_int_t), 1, f)) 
	  {
		fprintf(stderr, "ERROR: reading %s %d : n\n", name1, id1);
		return HOOK_UP_FILE_ERROR;
	  }	
/*---------------------------------------------*/
/* lecture de la derrière position des sources */
/*---------------------------------------------*/
	if (debug == 1) 
	{
		fprintf(stderr,"Nbrsource = %d\n",Nbrsource);
	}
	  id1 = 41;
	  if (1 != fread(&PosSource, sizeof(pastix_int_t), 1, f)) 
	  {
		fprintf(stderr, "ERROR: reading %s %d : n\n", name1, id1);
		return HOOK_UP_FILE_ERROR;
	  }
/*-----------------------------------------------------*/	  
/* lecture du nombre de total de Toron à modéliser	   */
/*-----------------------------------------------------*/

	  id1 = 5;
	  if (1 != fread(&NbToron, sizeof(pastix_int_t), 1, f)) 
	  {
		fprintf(stderr, "ERROR: reading %s %d : n\n", name1, id1);
		return HOOK_UP_FILE_ERROR;
	  }	

	if (debug == 1) 
	{
		fprintf(stderr,"NbToron = %d\n",NbToron);
	}
/*-----------------------------------------------------------*/	  
/*      Lecture des propriété des fils de chaque Toron	     */
/*-----------------------------------------------------------*/

/*---allocation de la mémoire Tableau de Nombre de fils Nombre de cellules (découpage du Toron en mailles) et celui de la matrice des propriétés---*/


	    id1 = 6;
/*--- Allocation mémoire et lecture  Tableau Nombre de cellules par Toron ---*/		 
		
		if (0 != (ret = alloc_read_file_int(f,&NbCellule,&NbToron,name1,id1)))
		{
			return ret;
		}
	 
		id1 = 7;		
/*--- Allocation mémoire et lecture  Tableau Nombre de fils par Toron ---*/		 
		
		if (0 != (ret = alloc_read_file_int(f,&Nbfils,&NbToron,name1,id1)))
		{
			return ret;
		}
	    	
		if (debug == 1) 
		{
			for (i=0;i<NbToron;i++)
			{
				fprintf(stderr,"Nbfils[%d] = %d  NbCellule[%d] = %d \n",i,Nbfils[i],i,NbCellule[i]);
			}
		}


		
/*--- 1ère dim Allocation mémoire matrice capacité ---*/
		
		if (NULL == (valCap = malloc(NbToron*sizeof(double*))))
		return MEMORY_ERROR;
		
/*--- 1ère dim Allocation mémoire matrice inductance ---*/
		
		if (NULL == (valind = malloc(NbToron*sizeof(double*))))
		return MEMORY_ERROR;
	
/*--- 1ère dim Allocation mémoire matrice résisitance ---*/
		
		if (NULL == (valcon = malloc(NbToron*sizeof(double*))))
		return MEMORY_ERROR;

/*--- 1ère dim Allocation mémoire matrice des connections des Resistance---*/

		if (NULL == (ConnectionRes = malloc(NbToron*sizeof(pastix_int_t*))))
		return MEMORY_ERROR;
	
/*--- 1ère dim Allocation mémoire matrice des connections des Inductance---*/
		
		if (NULL == (ConnectionInd = malloc(NbToron*sizeof(pastix_int_t*))))
		return MEMORY_ERROR;
		
	  for (i=0;i<NbToron;i++)
	  {
			id1 = -1;
		/*--- 2ème dim Allocation mémoire matrice résisitance et lecture des données---*/

			if (NULL == (valcon[i] = malloc(*(Nbfils+i)*sizeof(double))))
			return MEMORY_ERROR;
		
			for (k=0;k<*(Nbfils+i);k++)
			{
				if (1 != fread(&valcon[i][k], sizeof(double), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d : colptr\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
			}
			
			id1 = 7;
		/*--- 2ème dim Allocation mémoire matrice inductance et lecture des données---*/
		
			if (NULL == (valind[i] = malloc(*(Nbfils+i)*sizeof(double))))
			return MEMORY_ERROR;
		
			for (k=0;k<*(Nbfils+i);k++)
			{
				if (1 != fread(&valind[i][k], sizeof(double), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d : colptr\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
			}		
		
			id1 = 8;
		/*--- 2ème dim Allocation mémoire matrice capacité et lecture des données---*/
		
			if (NULL == (valCap[i] = malloc(*(Nbfils+i)*sizeof(double))))
			return MEMORY_ERROR;
		
			for (k=0;k<*(Nbfils+i);k++)
			{
				if (1 != fread(&valCap[i][k], sizeof(double), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d : colptr\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
			}

			id1 = 9;
		/*--- 2ème dim Allocation mémoire matrice des connections des resistances et lecture des données---*/
			ii = 2 * (*(Nbfils + i));

			if (NULL == (ConnectionRes[i] = malloc(ii*sizeof(pastix_int_t))))
			return MEMORY_ERROR;
		
			for (k=0;k<ii;k++)
			{
				if (1 != fread(&ConnectionRes[i][k], sizeof(pastix_int_t), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d : colptr\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
			}
			
			id1 = 10;
		/*--- 2ème dim Allocation mémoire matrice des connections des inductances et lecture des données---*/ 
		
			if (NULL == (ConnectionInd[i] = malloc(ii*sizeof(pastix_int_t))))
			return MEMORY_ERROR;
		
			for (k=0;k<ii;k++)
			{
				if (1 != fread(&ConnectionInd[i][k], sizeof(pastix_int_t), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d : colptr\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
			}		
	  }
/*--- 1ère dim Allocation mémoire matrice cubique liste des couple de fils par Toron ---*/

		if (NULL == (couple =(pastix_int_t***)malloc(NbToron*sizeof(pastix_int_t**))))
		return MEMORY_ERROR;
	
/*--- 1ère dim Allocation mémoire matrice cubique mutuelle 1 ---*/

		if (NULL == (valmut1 =(double***)malloc(NbToron*sizeof(double**))))
		return MEMORY_ERROR;
	
		
/*--- 1ère dim Allocation mémoire matrice cubique mutuelle 2 ---*/

		if (NULL == (valmut2 = (double***)malloc(NbToron*sizeof(double**))))
		return MEMORY_ERROR;
		
/*--- 1ère dim Allocation mémoire matrice cubique mutuelle entre 1 et 2 ---*/

		if (NULL == (valmut12 = (double***)malloc(NbToron*sizeof(double**))))
		return MEMORY_ERROR;

/*--- 1ère dim Allocation mémoire matrice cubique capacité entre 1 et 2 ---*/

		if (NULL == (valsCap = (double***)malloc(NbToron*sizeof(double**))))
		return MEMORY_ERROR;
	
	  for (i=0;i<NbToron;i++)
	  {

			/*--- 2ème dim Allocation mémoire matrice cubique des couple de fils par Toron ---*/
			
			if (NULL == (couple[i] =(pastix_int_t**)malloc(Nbfils[i]*sizeof(pastix_int_t*))))
			return MEMORY_ERROR;
			
			/*--- 2ème dim Allocation mémoire matrice cubique mutuelle 1 ---*/
			
			if (NULL == (valmut1[i] =(double**)malloc(Nbfils[i]*sizeof(double*))))
			return MEMORY_ERROR;			

			/*--- 2ème dim Allocation mémoire matrice cubique mutuelle 2 ---*/
			
			if (NULL == (valmut2[i] =(double**)malloc(Nbfils[i]*sizeof(double*))))
			return MEMORY_ERROR;			
						
			/*--- 2ème dim Allocation mémoire matrice cubique mutuelle entre 1 et 2 ---*/

			if (NULL == (valmut12[i] =(double**)malloc(Nbfils[i]*sizeof(double*))))
			return MEMORY_ERROR;			
			
			/*--- 2ème dim Allocation mémoire matrice cubique capacité entre 1 et 2 ---*/

			if (NULL == (valsCap[i] =(double**)malloc(Nbfils[i]*sizeof(double*))))
			return MEMORY_ERROR;
	  }
		
	  for (i=0;i<NbToron;i++)
	  {	  
			id1 = 11;
			for (j1=0;j1<*(Nbfils + i);j1++)
			{
				/*--- 3ème dim Allocation mémoire matrice cubique mutuelle 1---*/

				if (NULL == (couple[i][j1] = malloc(*(Nbfils+i)*sizeof(pastix_int_t))))
				return MEMORY_ERROR;	
			
				/*--- 3ème dim Allocation mémoire matrice cubique mutuelle 1---*/

				if (NULL == (valmut1[i][j1] = malloc(*(Nbfils+i)*sizeof(double))))
				return MEMORY_ERROR;				

				/*--- 3ème dim Allocation mémoire matrice cubique mutuelle 2---*/
				
				if (NULL == (valmut2[i][j1] = malloc(*(Nbfils+i)*sizeof(double))))
				return MEMORY_ERROR;					

				/*--- 3ème dim Allocation mémoire matrice cubique mutuelle entre 1 et 2---*/

				if (NULL == (valmut12[i][j1] = malloc(*(Nbfils+i)*sizeof(double))))
				return MEMORY_ERROR;
				
				/*--- 3ème dim Allocation mémoire matrice cubique capacité entre 1 et 2---*/

				if (NULL == (valsCap[i][j1] = malloc(*(Nbfils+i)*sizeof(double))))
				return MEMORY_ERROR;				

			}
	  }
			
	  for (i=0;i<NbToron;i++)
	  {
		 for (j1=0;j1<*(Nbfils + i);j1++)
		 {
			#ifdef _OPENMP
			#pragma omp parallel
			{
			#pragma omp for		 
			#endif		 
				 for (k=0;k<*(Nbfils + i);k++)
				 {
					couple[i][j1][k] = -1; 
				 }
			#ifdef _OPENMP
			}
			#endif		
		 }
	  }
	  
	  id1 = 12;	  
	  for (k=0;k<(NbToron);k++)
	  {
		  
		//lmax = (*(Nbfils + k)*(*(Nbfils + k)-1)/2);
		if (1 != fread(&lmax, sizeof(pastix_int_t), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d :\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
		
	    for (l=0;l<lmax;l++)
			{
				/* lecture de numéro du fil 1---*/
				if (1 != fread(&ii, sizeof(pastix_int_t), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d :\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
				
				/* lecture de numéro du fil 2---*/				
				if (1 != fread(&jj, sizeof(pastix_int_t), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d : n\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
				/* lecture de la valeur de mutuel du fil 1---*/
				if (1 != fread(&aux, sizeof(double), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d :\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
				else
				{
					couple[k][ii][jj] = 1;
					couple[k][jj][ii] = 1;					
					valmut1[k][ii][jj] = aux;
					valmut1[k][jj][ii] = valmut1[k][ii][jj];
					valmut1[k][jj][jj] = valmut1[k][ii][jj];
					valmut1[k][ii][ii] = valmut1[k][ii][jj];
				}				
				
				/* lecture de la valeur de mutuel du fil 2---*/
				if (1 != fread(&aux, sizeof(double), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d :\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
				else
				{
					valmut2[k][ii][jj] = aux; 
					valmut2[k][jj][ii] = valmut2[k][ii][jj];
					valmut2[k][jj][jj] = valmut2[k][ii][jj];
					valmut2[k][ii][ii] = valmut2[k][ii][jj];					
				}				
				
				/* lecture de la valeur de mutuel entre le fil 1 et le fil 2---*/
				if (1 != fread(&aux, sizeof(double), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d :\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
				else
				{
					valmut12[k][ii][jj] = aux;
					valmut12[k][jj][ii] = valmut12[k][ii][jj];
					valmut12[k][jj][jj] = valmut12[k][ii][jj];
					valmut12[k][ii][ii] = valmut12[k][ii][jj];					
				}				
				
				/* lecture de la valeur de capacité entre le fil 1 et le fil 2---*/
				if (1 != fread(&aux, sizeof(double), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d :\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
				else
				{
					valsCap[k][ii][jj] = aux;
					valsCap[k][jj][ii] = valsCap[k][ii][jj];
					valsCap[k][jj][jj] = valsCap[k][ii][jj];
					valsCap[k][ii][ii] = valsCap[k][ii][jj];						
				}
			}
	  }


	  
/*--- 1ère dim Allocation mémoire matrice contenant la liste de Câbles unifilaires blindee par Toron ---*/

		if (NULL == (Filsblindee =malloc(NbToron*sizeof(pastix_int_t*))))
		return MEMORY_ERROR;
	
/*--- 1ère dim Allocation mémoire matrice contenant les capacités des Câbles unifilaires blindee par Toron ---*/	
		if (NULL == (valCapBlind =malloc(NbToron*sizeof(double*))))

	return MEMORY_ERROR;


	id1 = 13;	  
	for (i=0;i<(NbToron);i++)
	{
		/*--- 2ème dim Allocation mémoire et initialisation à zeros de la matrice contenant la liste de Câbles unifilaires blindee par Toron ---*/
			
		if (NULL == (Filsblindee[i] =calloc(Nbfils[i],sizeof(pastix_int_t))))
		return MEMORY_ERROR;

		/*--- 2ème dim Allocation mémoire et initialisation à zeros de la matrice contenant les capacités des Câbles unifilaires blindee par Toron ---*/
			
		if (NULL == (valCapBlind[i] =calloc(Nbfils[i],sizeof(double))))
		return MEMORY_ERROR;
		
	}

	for (i=0;i<(NbToron);i++)
	{
		/* lecture de numéro du fil blindée---*/
		if (1 != fread(&lmax, sizeof(pastix_int_t), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d :\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
		
	    for (l=0;l<lmax;l++)
			{
				/* lecture de numéro du fil blindé---*/
				if (1 != fread(&ii, sizeof(pastix_int_t), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d :\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}
				
				/* si le fil est blindé alors Filsblindee[i][ii] = 1---*/
				Filsblindee[i][ii] = 1;
				
				/* lecture de la capacité du fil blindé---*/
				if (1 != fread(&dd, sizeof(double), 1, f)) 
				{
					fprintf(stderr, "ERROR: reading %s %d :\n", name1, id1);
					return HOOK_UP_FILE_ERROR;
				}

				valCapBlind[i][ii] = dd;				
			}
	}
	/*Resistance*/
	New_sizecolptrres = (*rowscon)[*ncon]-1;
	
	/*Inductance*/
	New_sizecolptrind = (*rowsind)[*nind]-1;
	
	/*Capacité*/
	New_sizecolptrcap = (*rowscap)[*ncap]-1;
	
		
	if (debug == 1) 
	{
		printf("rowscon[%d] = %d rowsind[%d] = %d rowscap[%d] = %d\n",*ncon-1,(*rowscon)[*ncon-1],*nind-1,(*rowsind)[*nind-1],*ncap-1,(*rowscap)[*ncap-1]);
		printf("rowscon[%d] = %d rowsind[%d] = %d rowscap[%d] = %d\n",*ncon,(*rowscon)[*ncon],*nind,(*rowsind)[*nind],*ncap,(*rowscap)[*ncap]);
	}
	
		incon = *ncon;
		
	if (debug == 1) 
	{
		printf("ncon0 = %d \n",*ncon);
	}
		*ncon = (Nbequipnsres - Nbrsource); 
		*ncon += (Nbequipnsind + Nbequipnscap) ;
		*ncon += 2*Nbrsource;
		//*ncon = NbrAdd;

	m = 0 ;
	if (debug == 1) 
	{	
		ff17 = fopen("filconnectes", "w+");
	}
	for (i = 0; i<(NbToron-1) ; i++)
	{
		for (j = i+1; j<NbToron ; j++)
		{	
			//#ifdef _OPENMP
			//#pragma omp parallel
			//{
			//#pragma omp for reduction(+:m)		 
			//#endif
			for(k=0;k<*(Nbfils + i);k++)
			{
				for(l=0;l<*(Nbfils + j);l++)
				{
					if((ConnectionRes[i][2*k]==ConnectionInd[j][2*l])
					  ||(ConnectionRes[i][2*k]==ConnectionInd[j][(2*l)+1])
					  ||(ConnectionRes[i][(2*k)+1]==ConnectionInd[j][2*l])
					  ||(ConnectionRes[i][(2*k)+1]==ConnectionInd[j][(2*l)+1])
					  ||(ConnectionRes[j][2*l]==ConnectionInd[i][2*k])
					  ||(ConnectionRes[j][2*l]==ConnectionInd[i][(2*k)+1])
					  ||(ConnectionRes[j][(2*l)+1]==ConnectionInd[i][2*k])
					  ||(ConnectionRes[j][(2*l)+1]==ConnectionInd[i][(2*k)+1]))
					{
						if (debug == 1) 
						{	
							fprintf(ff17,"i = %d j=%d k=%d l=%d \n",i,j,k,l);
						}
						
						m++;
					}				  
				}
			}
			//#ifdef _OPENMP
			//}
			//#endif
		}
	}
	
	if (debug == 1) 
	{
		fclose(ff17);
	}
	
	if (debug == 1) 
	{
		printf("ncon1 = %d \n",*ncon);
	}
	for (i=0;i<NbToron;i++)
	{
		*ncon += ((2*(NbCellule[i]-1)) + 1) * Nbfils[i];
	}
	if (debug == 1) 
	{
		printf("m = %d ncon2 = %d \n",m,*ncon);
	}
	*ncon += m;
	if (debug == 1) 
	{
		printf("ncon2 = %d \n",*ncon);
	}
	
	for (i=0;i<NbToron;i++)
	{
		for (j=0;j<Nbfils[i];j++)
		{		
			if (Filsblindee[i][j] == 1) 
			{
				*ncon += NbCellule[i];
			}
		}
	}
	
	if (debug == 1) 
	{
		printf("ncon3 = %d \n",*ncon);
	}
	
	*ncon = PosSource;
	
	for (i=0;i<NbToron;i++)
	{
		for (j=0;j<Nbfils[i]-1;j++)
		{
			for (k=j+1;k<Nbfils[i];k++)
			{
				if (couple[i][j][k]==1)
				{
					*ncon += 2*NbCellule[i]; 
				}
			}
		}
	}

	if (debug == 1) 
	{
		printf("ncon4 = %d \n",*ncon);
	}
	
	*ncap = *ncon ; 		
	*nind = *ncon ;

	if (*ncon>incon)
	{
		if (0 != (ret = memory_allocation(0 ,ncon,rowscon,valuescon)))
		{ 
			return ret;
		}
		
			if (0 != (ret = memory_allocation(0 ,nind,rowsind,valuesind)))
		{ 
			return ret;
		}	

		if (0 != (ret = memory_allocation(0 ,ncap,rowscap,valuescap)))
		{ 
			return ret;
		}
			
		if (debug == 1) 
		{
			printf("incon = %d ncon = %d \n",incon,*ncon);
		}

#ifdef _OPENMP		
#pragma omp parallel shared(rowscon,New_sizecolptrres)
	{
    #pragma omp for nowait	
#endif
		for (i=incon+1; i<=*ncon; i++)
		{
			if (New_sizecolptrres!=0)
			{
				(*rowscon)[i] = New_sizecolptrres+1;
			}
			else
			{
				(*rowscon)[i] = 1;
			}

			if (New_sizecolptrind!=0)
			{
				(*rowsind)[i] = New_sizecolptrind+1;
			}
			else
			{
				(*rowsind)[i] = 1;
			}

			if (New_sizecolptrcap!=0)
			{
				(*rowscap)[i] = New_sizecolptrcap+1;
			}
			else
			{
				(*rowscap)[i] = 1;
			}			
				
			if (debug == 1) 
			{
				printf("(*rowscon)[%d] = %d (*rowsind)[%d] = %d (*rowscap)[%d] = %d\n",i,(*rowscon)[i],i,(*rowsind)[i],i,(*rowscap)[i]);
			}
			
		}
#ifdef _OPENMP		
	}
#endif
	}
	
	fclose(f);
	
	if (debug == 1) 
	{
		fprintf(stderr," fin read_hook_up\n");
	}
	
/************************************/
/*							        */
/*   	     Remplissage        	*/
/*			des  matrices           */
/*								    */
/************************************/ 

	
	 R = Nbequipnsres + Nbequipnscap + Nbequipnsind + Nbrsource + 1;
	 //R2 = Nbequipnsres + Nbequipnscap + Nbequipnsind + Nbrsource + 1;
	 R4 = 0;

	if (debug == 1)
	{
		ff1 = fopen("posRes", "w+");
		ff2 = fopen("posInd", "w+");
		ff3 = fopen("posCap", "w+");
		
		fprintf(ff1,"R = %d\n",R);	
		fprintf(ff2,"R = %d\n",R);			
		fprintf(ff3,"R = %d\n",R);		
	}
	
	 R1 = MIN(ConnectionRes[0][0],ConnectionRes[0][1]);

	 max1 = 0 ;
	for (i = 0; i<NbToron ; i++)
	{
		#ifdef _OPENMP
		#pragma omp parallel
		{
		#pragma omp for reduction(max:max1)		 
		#endif
		for(j=0;j<*(Nbfils + i);j++)
		{
			max1  = MAX(max1,ConnectionRes[i][2*j]);
			max1  = MAX(max1,ConnectionRes[i][(2*j)+1]);
			max1  = MAX(max1,ConnectionInd[i][2*j]);			
			max1  = MAX(max1,ConnectionInd[i][(2*j)+1]);
		}
		#ifdef _OPENMP
		}
		#endif
	}
	
	R2 = max1 + 1 ;
	if (debug == 1)
	{		
		fprintf(ff1,"R2 = %d\n",R2);	
		fprintf(ff2,"R2 = %d\n",R2);			
		fprintf(ff3,"R2 = %d\n",R2);		
	}
    id1 = 0;
	R3 = PosSource;
	R6 = 0;
	R7 = 0;	
	R8 = 0;
	R9 = 0;
	
	 
	if (NULL == (LigneRes = calloc((*ncon),sizeof(int))))
	{
		return MEMORY_ERROR;
	}
	
	if (NULL == (LigneInd = calloc((*nind),sizeof(int))))
	{
		return MEMORY_ERROR;
	}

	if (NULL == (LigneCap = calloc((*ncap),sizeof(int))))
	{
		return MEMORY_ERROR;
	}

				/*****************************/
				/**    Repositionnement     **/ 
				/**	 des sources et autres  **/
				/*****************************/	
	for (i = 0; i<*ncon ; i++)
	{
		LigneRes[i] = (*rowscon)[i+1] - (*rowscon)[i];
		LigneInd[i] = (*rowsind)[i+1] - (*rowsind)[i];
		LigneCap[i] = (*rowscap)[i+1] - (*rowscap)[i];
		
		if (debug == 1)
		{		
			fprintf(ff1,"(LigneRes)[%d] = %d\n",i,LigneRes[i]);	
			fprintf(ff2,"(LigneInd)[%d] = %d\n",i,LigneInd[i]);			
			fprintf(ff3,"(LigneCap)[%d] = %d\n",i,LigneCap[i]);
		}
	}

	if (debug == 1)
	{
		fprintf(ff1,"New_sizecolptrres = %d\n",New_sizecolptrres);	
		fprintf(ff2,"New_sizecolptrind = %d\n",New_sizecolptrind);			
		fprintf(ff3,"New_sizecolptrcap = %d\n",New_sizecolptrcap);	
		
		printf("New_sizecolptrres = %d\n",New_sizecolptrres);	
		printf("New_sizecolptrind = %d\n",New_sizecolptrind);			
		printf("New_sizecolptrcap = %d\n",New_sizecolptrcap);		
	}
	
	
	if (New_sizecolptrres!=0)
	{
		if (NULL == (TabrowsRes = (int*) calloc(New_sizecolptrres,sizeof(pastix_int_t))))
			{
				return MEMORY_ERROR;
			}
			
		if (NULL == (TabcolRes = (int*) calloc(New_sizecolptrres,sizeof(pastix_int_t))))
			{
				return MEMORY_ERROR;
			}
			
		if (NULL == (TabValuesRes = (double*) calloc(New_sizecolptrres,sizeof(double))))
			{
				return MEMORY_ERROR;
			}
	}
	if (New_sizecolptrind!=0)
	{	
		if (NULL == (TabrowsInd = (int*) calloc(New_sizecolptrind,sizeof(pastix_int_t))))
			{
				return MEMORY_ERROR;
			}
		if (NULL == (TabcolInd = (int*) calloc(New_sizecolptrind,sizeof(pastix_int_t))))
			{
				return MEMORY_ERROR;
			}
			
		if (NULL == (TabValuesInd = (double*) calloc(New_sizecolptrind,sizeof(double))))
			{
				return MEMORY_ERROR;
			}
	}
	if (New_sizecolptrcap!=0)
	{	
		if (NULL == (TabrowsCap = (int*) calloc(New_sizecolptrcap,sizeof(pastix_int_t))))
			{
				return MEMORY_ERROR;
			}
		if (NULL == (TabcolCap = (int*) calloc(New_sizecolptrcap,sizeof(pastix_int_t))))
			{
				return MEMORY_ERROR;
			}
			
		if (NULL == (TabValuesCap = (double*) calloc(New_sizecolptrcap,sizeof(double))))
			{
				return MEMORY_ERROR;
			}		
	}

	NbRes =-1 ;
	NbInd =-1 ;
	NbCap =-1 ;

	if ((New_sizecolptrres!=0) || (New_sizecolptrind!=0) || (New_sizecolptrcap!=0))
	{
		for (i = 0; i<*ncon ; i++)
		{
				for (j=0; j<LigneRes[i];j++) 
				{
					NbRes++;
					TabrowsRes[NbRes] = i+1;
					TabcolRes[NbRes] = (*colptrcon)[(*rowscon)[i] - 1 + j];
					TabValuesRes[NbRes] = (*valuescon)[(*rowscon)[i] - 1 + j];
					if (debug == 1)
					{		
						fprintf(ff1,"(TabrowsRes)[%d] = %d  TabcolRes[%d] = %d TabValuesRes[%d] = %f\n",NbRes,TabrowsRes[NbRes],NbRes,TabcolRes[NbRes],NbRes,TabValuesRes[NbRes]);	
					}					
				}
				for (j=0; j<LigneInd[i];j++) 
				{
					NbInd++;
					TabrowsInd[NbInd] = i+1;
					TabcolInd[NbInd] = (*colptrind)[(*rowsind)[i] - 1 + j];
					TabValuesInd[NbInd] = (*valuesind)[(*rowsind)[i] - 1 + j];
					if (debug == 1)
					{		
						fprintf(ff2,"(TabrowsInd)[%d] = %d  TabcolInd[%d] = %d TabValuesInd[%d] = %E\n",NbInd,TabrowsInd[NbInd],NbInd,TabcolInd[NbInd],NbInd,TabValuesInd[NbInd]);	
					}					
				}
				for (j=0; j<LigneCap[i];j++) 
				{
					NbCap++;
					TabrowsCap[NbCap] = i+1;
					TabcolCap[NbCap] = (*colptrcap)[(*rowscap)[i] - 1 + j];
					TabValuesCap[NbCap] = (*valuescap)[(*rowscap)[i] - 1 + j];
					if (debug == 1)
					{		
						fprintf(ff3,"(TabrowsCap)[%d] = %d  TabcolCap[%d] = %d TabValuesCap[%d] = %E\n",NbCap,TabrowsCap[NbCap],NbCap,TabcolCap[NbCap],NbCap,TabValuesCap[NbCap]);	
					}						
				}			
		}
	}
	if (debug == 1)
	{		
		fclose(ff1);
		fclose(ff3);
		fclose(ff2);
	}

	
/*---allocation de la mémoire pour le tableau des positions pour chaque portion de fil du Toron ---*/
	if (NULL == (Tabposition = (int****) malloc(NbToron*sizeof(int***))))
	{
		return MEMORY_ERROR;
	}
	
	for (i = 0; i<NbToron ; i++)
	{		
		if (NULL == (Tabposition[i] = (int***) malloc(*(Nbfils + i)*sizeof(int**))))
		{
			return MEMORY_ERROR;
		}
		
		for(j=0;j<Nbfils[i];j++)
		{
			if (NULL == (Tabposition[i][j] = (int**) malloc(*(NbCellule + i)*sizeof(int*))))
			{
				return MEMORY_ERROR;
			}			
		}
		
		for(j=0;j<Nbfils[i];j++)
		{
			for(k=0;k<NbCellule[i];k++)
			{				
				if (NULL == (Tabposition[i][j][k] = calloc(5,sizeof(int))))
				{
					return MEMORY_ERROR;
				}	
			}
		}
	}
	
	Old_sizecolptrres = New_sizecolptrres; 
	Old_sizecolptrind = New_sizecolptrind; 
	Old_sizecolptrcap = New_sizecolptrcap;
	
	if (debug == 1)
	{	
		printf("Old_sizecolptrres = %d  Old_sizecolptrind = %d  Old_sizecolptrcap = %d\n",Old_sizecolptrres,Old_sizecolptrind,Old_sizecolptrcap);
	}

	if (0 != (ret = taille_values_maj_rows(R,R2,PosSource,NbToron,*ncon,Nbfils,NbCellule,&LigneRes,&LigneInd,&LigneCap,ConnectionRes,ConnectionInd,Filsblindee,couple,&New_sizecolptrres,&New_sizecolptrind,&New_sizecolptrcap,&Tabposition,colptrcon,colptrcap,colptrind,rowscon,rowscap,rowsind,&valCapBlind,&valCap,&valind,&valcon,&valmut1,&valmut2,&valmut12,&valsCap)))
	{
		return ret;
	}
	
	if (debug == 1)
	{		
		printf("New_sizecolptrres = %d  New_sizecolptrind = %d  New_sizecolptrcap = %d\n",New_sizecolptrres,New_sizecolptrind,New_sizecolptrcap);
		ff1 = fopen("NewRowsRes", "w+");
		ff2 = fopen("NewRowsInd", "w+");
		ff3 = fopen("NewRowsCap", "w+");
	}
	
	(*rowscon)[*ncon] = New_sizecolptrres + 1;
	(*rowsind)[*ncon] = New_sizecolptrind + 1;
	(*rowscap)[*ncon] = New_sizecolptrcap + 1;
	
	for (i = *ncon-1; i>=0 ; i--)
	{
		(*rowscon)[i] = (*rowscon)[i+1] - LigneRes[i];
		(*rowsind)[i] = (*rowsind)[i+1] - LigneInd[i];
		(*rowscap)[i] = (*rowscap)[i+1] - LigneCap[i];
		if (debug == 1)
		{			
			fprintf(ff1,"(*rowscon)[%d] = %d LigneRes[%d] = %d\n",i,(*rowscon)[i],i,LigneRes[i]);	
			fprintf(ff2,"(*rowsind)[%d] = %d LigneInd[%d] = %d\n",i,(*rowsind)[i],i,LigneInd[i]);			
			fprintf(ff3,"(*rowscap)[%d] = %d LigneCap[%d] = %d\n",i,(*rowscap)[i],i,LigneCap[i]);
		}			
	}
	if (debug == 1)
	{	
		fclose(ff1);
		fclose(ff3);
		fclose(ff2);
	}
	if (debug == 1)
	{	
		ff1 = fopen("Resistance", "w");
		fclose(ff1);
		ff1 = fopen("Resistance", "w");
		fclose(ff1);
		ff1 = fopen("Inductance", "w");	
		fclose(ff1);
	}		
/* allocation mémoire pour le tableau values pour les trois matrice résistance, inductance et capacitance*/
					/**********************/
					/**    Résistance    **/
					/**********************/
	if (0 != (ret = memory_allocation2(&New_sizecolptrres,colptrcon,valuescon)))
	{ 
		return ret;
	}
	
					/**********************/
					/**    Inductance    **/
					/**********************/	
	if (0 != (ret = memory_allocation2(&New_sizecolptrind,colptrind,valuesind)))
	{ 
		return ret;
	}
					/**********************/
					/**     Capacité     **/
					/**********************/
	if (0 != (ret = memory_allocation2(&New_sizecolptrcap,colptrcap,valuescap)))
	{ 
		return ret;
	}
	
	
				/*****************************/
				/**    Repositionnement     **/ 
				/**	 des sources et autres  **/
				/*****************************/
							
	for (i = 0; i<Old_sizecolptrres ; i++)
	{
		id1 = -1;
		Inserer_valeur_CRS(TabrowsRes[i],TabcolRes[i],id1,TabValuesRes[i],&New_sizecolptrres,colptrcon,rowscon,valuescon,&LigneRes);
	}
	
	for (i = 0; i<Old_sizecolptrind ; i++)
	{
		id1 = -2;
		Inserer_valeur_CRS(TabrowsInd[i],TabcolInd[i],id1,TabValuesInd[i],&New_sizecolptrind,colptrind,rowsind,valuesind,&LigneInd);		
	}

	for (i = 0; i<Old_sizecolptrcap ; i++)
	{
		id1 = -3;
		Inserer_valeur_CRS(TabrowsCap[i],TabcolCap[i],id1,TabValuesCap[i],&New_sizecolptrcap,colptrcap,rowscap,valuescap,&LigneCap);
	}

				/*********************************/
				/**        Insertion du         **/ 
				/**	 Schéma des télégraphistes  **/
				/**		pour chaque fils 	    **/
				/*********************************/
	R9 = R3;				
	for (i = 0; i<NbToron ; i++)
	{
		printf("\n**************\n   Toron %d  \n**************\n",i+1);		 
	
		for(j=0;j<*(Nbfils + i);j++)
		{
			
			for (k=0;k<NbCellule[i];k++)
			{
				#ifdef _OPENMP
				#pragma omp parallel firstprivate(Tabposition) private(R1,R2,id1) shared(i,j,k) num_threads(2)
				{
				#pragma omp sections nowait
				{					
				#pragma omp section 
				{
				#endif
															/**********************/
															/**    Résistance    **/
															/**********************/
				R1 = Tabposition[i][j][k][0];
				R2 = Tabposition[i][j][k][1];
				
				id1 = 1;
				Inserer_valeur_CRS(R1,R1,id1,valcon[i][j],&New_sizecolptrres,colptrcon,rowscon,valuescon,&LigneRes);
				
				if (R2<R1)
				{	
					id1 = 2;
					Inserer_valeur_CRS(R1,R2,id1,(-1.0)*valcon[i][j],&New_sizecolptrres,colptrcon,rowscon,valuescon,&LigneRes);
				}
				else
				{
					id1 = 2;
					Inserer_valeur_CRS(R2,R1,id1,(-1.0)*valcon[i][j],&New_sizecolptrres,colptrcon,rowscon,valuescon,&LigneRes);
				}
				
				
				id1 = 3;
				Inserer_valeur_CRS(R2,R2,id1,valcon[i][j],&New_sizecolptrres,colptrcon,rowscon,valuescon,&LigneRes);
				#ifdef _OPENMP
				}//end of 1st section Openmp
				#pragma omp section 
				{				
				#endif
				
															/**********************/
															/**    Inductance    **/
															/**********************/
				
				R1 = Tabposition[i][j][k][2];
				R2 = Tabposition[i][j][k][3];	
				if (R2<R1)
				{	
					id1 = 4;
					Inserer_valeur_CRS(R1,R2,id1,(-1.0)*valind[i][j],&New_sizecolptrind,colptrind,rowsind,valuesind,&LigneInd);									

				}
				else
				{
					id1 = 4;
					Inserer_valeur_CRS(R2,R1,id1,(-1.0)*valind[i][j],&New_sizecolptrind,colptrind,rowsind,valuesind,&LigneInd);									
				}
				
				id1 = 5;
				Inserer_valeur_CRS(R1,R1,id1,valind[i][j],&New_sizecolptrind,colptrind,rowsind,valuesind,&LigneInd);					
				
				id1 = 6;
				Inserer_valeur_CRS(R2,R2,id1,valind[i][j],&New_sizecolptrind,colptrind,rowsind,valuesind,&LigneInd);
				
															/**********************/
															/**     Capacité     **/
															/**********************/
				
				if (Filsblindee[i][j] == 1) 
				{
					id1 = 7;
					R8 = Tabposition[i][j][k][5];
					Inserer_valeur_CRS(R8 + 1,R8,id1,(-1.0)*valCapBlind[i][j],&New_sizecolptrcap,colptrcap,rowscap,valuescap,&LigneCap);
						
					id1 = 8;
					Inserer_valeur_CRS(R8 + 1,R8 + 1,id1,valCapBlind[i][j],&New_sizecolptrcap,colptrcap,rowscap,valuescap,&LigneCap);
				}
				else
				{
					id1 = 77;
					Inserer_valeur_CRS(R2,R2,id1,valCap[i][j],&New_sizecolptrcap,colptrcap,rowscap,valuescap,&LigneCap);
				}
				#ifdef _OPENMP
				}//end of 3nd section Openmp					
				}//end of sections Openmp
				}				
				#endif
			}
		}
		
															/**********************/
															/**     Mutuelle     **/
															/**********************/
		
		for(j=0;j<(Nbfils[i]-1);j++)
		{
			for(k=j+1;k<Nbfils[i];k++)
			{
				if (couple[i][j][k]==2)
				{
					couple[i][j][k]= -1 ;
					couple[i][k][j]= -1 ;				

					//printf("j = %d k = %d NbCellule[%d] = %d\n",j,k,i,NbCellule[i]);				
					
					#ifdef _OPENMP
					#pragma omp parallel private(l,R3,R4,R5,R6,R7,id1) firstprivate(i,j,k,NbCellule,Tabposition) num_threads(2)
					{
					#pragma omp sections nowait
					{					
					#pragma omp section 
					{
					#endif
															/**********************/
															/**    Résistance    **/
															/**********************/					
					R3 = R9;
					for (l=0;l<NbCellule[i];l++)
					{
						R4 = Tabposition[i][j][l][2];
						R6 = Tabposition[i][j][l][3];
						
						R5 = Tabposition[i][k][l][2];
						R7 = Tabposition[i][k][l][3];
						
						id1 = 9;
						Inserer_valeur_CRS(R3,R4,id1,(-1.0),&New_sizecolptrres,colptrcon,rowscon,valuescon,&LigneRes);
						id1 = 10;
						Inserer_valeur_CRS(R3,R6,id1,(1.0),&New_sizecolptrres,colptrcon,rowscon,valuescon,&LigneRes);
						id1 = 11;
						Inserer_valeur_CRS((R3+1),R5,id1,(-1.0),&New_sizecolptrres,colptrcon,rowscon,valuescon,&LigneRes);										
						id1 = 12;
						Inserer_valeur_CRS((R3+1),R7,id1,(1.0),&New_sizecolptrres,colptrcon,rowscon,valuescon,&LigneRes);
						R3+=2;						
					}
															/**********************/
															/**     Capacité     **/
															/**********************/					
					#ifdef _OPENMP
					}//end of 1st section Openmp
					#pragma omp section 
					{				
					#endif
					R3 = R9;
					for (l=0;l<NbCellule[i];l++)
					{
						id1 = 13;
						Inserer_valeur_CRS(R3,R3,id1,valmut1[i][j][k],&New_sizecolptrcap,colptrcap,rowscap,valuescap,&LigneCap);
						id1 = 14;
						Inserer_valeur_CRS(R3+1,R3,id1,valmut12[i][j][k],&New_sizecolptrcap,colptrcap,rowscap,valuescap,&LigneCap);
						id1 = 15;
						Inserer_valeur_CRS(R3+1,R3+1,id1,valmut2[i][j][k],&New_sizecolptrcap,colptrcap,rowscap,valuescap,&LigneCap);				
						R3+=2;
				
					}	
					#ifdef _OPENMP
					}//end of 3nd section Openmp					
					}//end of sections Openmp
					}				
					#endif	
					R9+= (2*NbCellule[i]);							
															/**********************/
															/**     Capacité     **/
															/**********************/										

					for (l=0;l<NbCellule[i];l++)
					{					
						R6 = Tabposition[i][j][l][3];
						R7 = Tabposition[i][k][l][3];
						
						id1 = 16;
						Inserer_valeur_CRS(R6,R6,id1,valsCap[i][j][k],&New_sizecolptrcap,colptrcap,rowscap,valuescap,&LigneCap);
						id1 = 17;
						Inserer_valeur_CRS(R7,R7,id1,valsCap[i][j][k],&New_sizecolptrcap,colptrcap,rowscap,valuescap,&LigneCap);
									
						if (R7<R6)
						{
							id1 = 18;
							Inserer_valeur_CRS(R6,R7,id1,(-1.0)*valsCap[i][j][k],&New_sizecolptrcap,colptrcap,rowscap,valuescap,&LigneCap);
						}
						else
						{
							id1 = 18;
							Inserer_valeur_CRS(R7,R6,id1,(-1.0)*valsCap[i][j][k],&New_sizecolptrcap,colptrcap,rowscap,valuescap,&LigneCap);					
						}
					}			
				}
			}
		}				
	}

	if (debug == 1)
	{
		fprintf(stdout," free Tabposition\n");
	}
	for (i=0;i<NbToron;i++)
	{
		for(j=0;j<*(Nbfils + i);j++)
		{
			for(k=0;k<*(NbCellule + i);k++)
			{
				free(Tabposition[i][j][k]);					
			}
		}
	}
	for (i=0;i<NbToron;i++)
	{		
		for(j=0;j<*(Nbfils + i);j++)
		{
			free(Tabposition[i][j]);			
		}
	}
	for (i=0;i<NbToron;i++)
	{		
		free(Tabposition[i]);			
	}		
	
	free(Tabposition);
	
	 if (debug == 1) 
	{
		fclose(ff1);
		fclose(ff3);
		fclose(ff2);	
	}
	
	if (debug == 1)
	{
		fprintf(stdout," Avant free\n");
	}
	
	for (i=0;i<NbToron;i++)
	{
		free(ConnectionRes[i]);
		free(ConnectionInd[i]);
		free(valCap[i]);
		free(valind[i]);
		free(valcon[i]);
	}

	
	free(ConnectionRes);
	free(ConnectionInd);	
    free(valCap);
	free(valind);
	free(valcon);

	
	for (i=0;i<NbToron;i++)
	{	
		for (j=0;j<Nbfils[i];j++)
		{
			free(valmut1[i][j]);
			free(valmut2[i][j]);
			free(valmut12[i][j]);
			free(valsCap[i][j]);
		}
		
	}

	for (i=0;i<NbToron;i++)
	{	
		free(valmut1[i]);
		free(valmut2[i]);
		free(valmut12[i]);
		free(valsCap[i]);
	}
	
	free(valmut1);
	free(valmut2);
	free(valmut12);
	free(valsCap);	
	
	free(Nbfils);
	free(NbCellule);
	
	fprintf(stdout," fin remplissage_matrice\n");
	if (debug == 1)
	{
		f1 = fopen("Constants_line.txt", "w+");
		
		for (i=0;i<*ncon;i++)
		{
			if (i==(*ncon-1))
			{
				fprintf(f1,"(*LigneRes)[%d] = %d\n",i,((*rowscon)[i+1]-(*rowscon)[i])-1);
			}
			else
			{
				fprintf(f1,"(*LigneRes)[%d] = %d\n",i,((*rowscon)[i+1]-(*rowscon)[i]));
			}
		}	
		
		fclose(f1);    
		f1 = fopen("Constants_new.txt", "w+");
		
		for (i=0;i<=*ncon;i++)
		{
			fprintf(f1,"%d\n",(*rowscon)[i]);
		}
		
		for (i=0;i<New_sizecolptrres;i++)
		{
			fprintf(f1,"%d\n",(*colptrcon)[i]);
		}

		for (i=0;i<New_sizecolptrres;i++)
		{
			fprintf(f1,"%10.10f\n",(*valuescon)[i]);
		}
		
		fclose(f1);
		
		f1 = fopen("Capacite_new.txt", "w+");
		
		for (i=0;i<=*ncap;i++)
		{
			fprintf(f1,"%d\n",(*rowscap)[i]);
		}
		
		for (i=0;i<New_sizecolptrcap;i++)
		{
			fprintf(f1,"%d\n",(*colptrcap)[i]);
		}

		for (i=0;i<New_sizecolptrcap;i++)
		{
			fprintf(f1,"%e\n",(*valuescap)[i]);
		}

		fclose(f1);
		
		f1 = fopen("Inducatnce_new.txt", "w+");
		
		for (i=0;i<=*nind;i++)
		{
			fprintf(f1,"%d\n",(*rowsind)[i]);
		}
		
		for (i=0;i<New_sizecolptrind;i++)
		{
			fprintf(f1,"%d\n",(*colptrind)[i]);
		}

		for (i=0;i<New_sizecolptrind;i++)
		{
			fprintf(f1,"%10.10f\n",(*valuesind)[i]);
		}
		
		fprintf(stdout," fin writing matrice\n");		
		fclose(f1);
	}


	return NO_ERROR; 
}
 
int read_matrix(char * name,
                pastix_int_t   *n,
                pastix_int_t   **colptr,
                pastix_int_t   **rows,
                double         **values)

{
  static int id = 0;
  FILE * f = fopen(name, "rb");
  if (f == NULL) {
    char error[1024];
    sprintf(error, "%s:%d:fopen %s", __FILE__, __LINE__, name);
    perror(error);
    return MATRIX_READ_ERROR;
  }  if (1 != fread(n, sizeof(pastix_int_t), 1, f)) {
    fprintf(stderr, "ERROR: reading %s %d : n\n", name, id);
    return MATRIX_READ_ERROR;
  }
  if (n < 0) return MATRIX_READ_ERROR;

  if (NULL == (*colptr = malloc((*n+1)*sizeof(pastix_int_t))))
    return MEMORY_ERROR;

  if (*n+1 != fread(*colptr, sizeof(pastix_int_t), *n+1, f)) {
    fprintf(stderr, "ERROR: reading %s %d : colptr\n", name, id);
    free(*colptr);
    return MATRIX_READ_ERROR;
  }

  if (NULL == (*rows = malloc(((*colptr)[*n]-1)*sizeof(pastix_int_t)))) {
    free(*colptr);
    return MEMORY_ERROR;
  }
  if ((*colptr)[*n]-1 != fread(*rows, sizeof(pastix_int_t), (*colptr)[*n]-1, f)) {
    fprintf(stderr, "ERROR: reading %s %d : rows\n", name, id);
    free(*colptr);
    free(*rows);
    return MATRIX_READ_ERROR;
  }

  if (NULL == (*values = malloc(((*colptr)[*n]-1)*sizeof(double)))) {
    free(*colptr);
    free(*rows);
    return MEMORY_ERROR;
  }

  if ((*colptr)[*n] - 1 != fread(*values, sizeof(double), (*colptr)[*n]-1, f)) {
    fprintf(stderr, "ERROR: reading %s %d : values\n", name, id);
    free(*colptr);
    free(*rows);
    free(*values);
    return MATRIX_READ_ERROR;
  }
  id++;
  fclose(f);
  return NO_ERROR;
}

int read_small_matrix(char *name1,
				char *name11,
				char *name3,
				pastix_int_t   *incon,
                pastix_int_t   *n1,
                pastix_int_t   *n2,
                pastix_int_t   *n3,				
                pastix_int_t   **colptr1,				
                pastix_int_t   **colptr2,				
                pastix_int_t   **colptr3,
                pastix_int_t   **rows1,
                pastix_int_t   **rows2,
                pastix_int_t   **rows3,
                double         **values1,
                double         **values2,
                double         **values3)

{  
  int ret;

    if (0 != (ret = read_matrix(name1, n1, colptr1, rows1, values1)))
	{
		return ret;
	}
		
	if (0 != (ret = read_matrix(name11, n2, colptr2, rows2, values2)))
	{
		return ret;
	}
	
	if (0 != (ret = read_matrix(name3, n3, colptr3, rows3, values3)))
	{
		return ret;
	}
 
	*incon = *n1;			
  if (strcasecmp(name1,"Capacitance.mat")==0) 
  {
	if (strcasecmp(name11,"Inductance.mat")==0)
	{
		if (0 != (ret = remplissage_matrice(n3,n1,n2,rows3,rows1,rows2,colptr3,colptr1,colptr2,values3,values1,values2)))
		{
			return ret;
		}
	}
	else
	{
		if (0 != (ret = remplissage_matrice(n3,n1,n2,rows2,rows1,rows3,colptr2,colptr1,colptr3,values2,values1,values3)))
		{
			return ret;
		}
	}
  }
  else	if  (strcasecmp(name11,"Capacitance.mat")==0)
  {
	if (strcasecmp(name1,"Inductance.mat")==0)
	{
		if (0 != (ret = remplissage_matrice(n3,n2,n1,rows3,rows2,rows1,colptr3,colptr2,colptr1,values3,values2,values1)))
		{
			return ret;
		}
	}
	else
	{
		if (0 != (ret = remplissage_matrice(n1,n2,n3,rows1,rows2,rows3,colptr1,colptr2,colptr3,values1,values2,values3)))
		{
			return ret;
		}		
	}
  }
  else
  {
	if (strcasecmp(name1,"Inductance.mat")==0)
	{
		if (0 != (ret = remplissage_matrice(n2,n3,n1,rows2,rows3,rows1,colptr2,colptr3,colptr1,values2,values3,values1)))
		{
			return ret;
		}
	}
	else
	{
		if (0 != (ret = remplissage_matrice(n1,n3,n2,rows1,rows3,rows2,colptr1,colptr3,colptr2,values1,values3,values2)))
		{
			return ret;
		}
	}
  }
	
  
  return ret;
}

int read_vector(char * name, pastix_int_t n, pastix_int_t n1, double complex ** rhs) {
  int myn,i;
  FILE * f = fopen(name, "rb");
  if (f == NULL) {
    char error[1024];
    sprintf(error, "%s:%d:fopen %s", __FILE__, __LINE__, name);
    perror(error);
    return MATRIX_READ_ERROR;
  }
  //printf("read_vector 1\n");
  if (1 != (fread(&myn, sizeof(pastix_int_t), 1, f))) {
    fprintf(stderr, "ERROR: reading vector %s : n\n", name);
    return MATRIX_READ_ERROR;
  }
  //printf("read_vector 2  myn = %d n = %d\n",myn,n);
  if (myn < 0 ) return MATRIX_READ_ERROR;
  if (myn != n) return MATRIX_DIMENSIONS_ERROR;
  if (NULL == (*rhs = malloc(n*sizeof(double complex)))) {
    return MEMORY_ERROR;
  }
  //printf("read_vector 3\n");
  if (n != fread(*rhs, sizeof(double complex), n, f)) {
    fprintf(stderr, "ERROR: reading vector %s : rhs\n", name);
    free(*rhs);
    return MATRIX_READ_ERROR;
  }
   if (NULL == (*rhs = realloc(*rhs,n1*sizeof(double complex)))) {
    return MEMORY_ERROR;
  }
  for (i=n;i<n1;i++)
  {
	 (*rhs)[i] = 0; 
  }
  //printf("read_vector 4\n");
  fclose(f);
  return NO_ERROR;
}

int save_vector(pastix_int_t n, double complex * rhs, int * listoutputidx, int cursol) {
  char name[1024];
  FILE * f;

  sprintf(name, "sol_%d.mat", cursol);
  f = fopen(name, "wb");
  if (f == NULL) {
    return SOLUTION_WRITE_ERROR;
  }

  if (1 != fwrite(&n, sizeof(pastix_int_t), 1, f))
    return SOLUTION_WRITE_ERROR;
  if (listoutputidx) {
    int i;
    for (i = 1; i < listoutputidx[0]+1; i++)
      if (1 != fwrite(rhs+listoutputidx[i], sizeof(double complex), 1, f))
        return SOLUTION_WRITE_ERROR;
  } else {
    if (n != fwrite(rhs, sizeof(double complex), n, f))
      return SOLUTION_WRITE_ERROR;
  }
  fclose(f);
  sprintf(name, "%s.saved", name);
  f = fopen(name, "wb");
  if (f == NULL) {
    return SOLUTION_WRITE_ERROR;
  }
  fclose(f);

  return NO_ERROR;
}


int save_vector_uniq(pastix_int_t n, double complex * rhs, int * listoutputidx, int last) {
  static FILE * f = NULL;
  static FILE * f2 = NULL;
  static char name[1024], name2[1024];

  if (f == NULL) {
    sprintf(name, "all_sols.mat");
    f = fopen(name, "wb");
    if (f == NULL) {
      return SOLUTION_WRITE_ERROR;
    }
	if (debug == 1) {
      sprintf(name2, "all_sols.mat.txt");
      f2 = fopen(name2, "w");
      if (f2 == NULL) {
        return SOLUTION_WRITE_ERROR;
      }
	}
  }

  if (listoutputidx) {
    int i;
    for (i = 1; i < listoutputidx[0]+1; i++) {
      if (1 != fwrite(rhs+listoutputidx[i], sizeof(double complex), 1, f))
        return SOLUTION_WRITE_ERROR;
	  if (debug == 1) {
	    if (fprintf(f2,"%g %g\n",creal(rhs[listoutputidx[i]]),cimag(rhs[listoutputidx[i]])) < 0)
          return SOLUTION_WRITE_ERROR;
	  }
	}
  } else {
    if (1 != fwrite(&n, sizeof(pastix_int_t), 1, f))
      return SOLUTION_WRITE_ERROR;
    if (n != fwrite(rhs, sizeof(double complex), n, f))
      return SOLUTION_WRITE_ERROR;
  }
  if (last == 1) {
    fclose(f);
    sprintf(name, "%s.saved", name);
    f = fopen(name, "wb");
    if (f == NULL) {
      return SOLUTION_WRITE_ERROR;
    }
    fclose(f);
	if (debug == 1) fclose(f2);
  }
  return NO_ERROR;
}

static inline
void
increment_the_smallest_between_2(pastix_int_t * rowidx1, pastix_int_t *rows1,
                                 pastix_int_t * rowidx2, pastix_int_t *rows2,
                                 pastix_int_t * rows) {
  if (rows1[*rowidx1] < rows2[*rowidx2]) {
    if (rows) *rows = rows1[*rowidx1];
    (*rowidx1) ++;;
  } else {
    if (rows1[*rowidx1] == rows2[*rowidx2]) {
      (*rowidx1)++;
    }
    if (rows) *rows = rows2[*rowidx2];
    (*rowidx2)++;
  }
}

#define RETURN(ret) do {                        \
    FILE * f = fopen("return.txt","w");         \
    fprintf(f, "%d\n", ret);                    \
    fclose(f);                                  \
    return ret;                                 \
  } while (0)

int main (int argc, char **argv)
{
  pastix_int_t    incon;              /* First Size of the matrix                                  */
  pastix_int_t    n1;                 /* Size of the matrix                                        */
  pastix_int_t   *colptr1     = NULL; /* Indexes of first element of each column in row and values */
  pastix_int_t   *rows1       = NULL; /* Row of each element of the matrix                         */
  double         *values1     = NULL; /* Value of each element of the matrix                       */
  pastix_int_t    n2;                 /* Size of the matrix                                        */
  pastix_int_t   *colptr2     = NULL; /* Indexes of first element of each column in row and values */
  pastix_int_t   *rows2       = NULL; /* Row of each element of the matrix                         */
  double         *values2     = NULL; /* Value of each element of the matrix                       */
  pastix_int_t    n3;                 /* Size of the matrix                                        */
  pastix_int_t   *colptr3     = NULL; /* Indexes of first element of each column in row and values */
  pastix_int_t   *rows3       = NULL; /* Row of each element of the matrix                         */
  double         *values3     = NULL; /* Value of each element of the matrix                       */
  double complex *rhs         = NULL; /* right hand side                                           */
  double complex *ax          = NULL; /* A times X product                                         */
  char            type[4]     = "RUA"; /* type of the matrix                                        */
  double freq;
  pastix_int_t    n;                  /* Size of the matrix                                        */
  pastix_int_t   *colptr      = NULL; /* Indexes of first element of each column in row and values */
  pastix_int_t   *rows        = NULL; /* Row of each element of the matrix                         */
  double complex *values      = NULL; /* Value of each element of the matrix                       */
  double complex *sol;
  double complex *solsaved;
  pastix_data_t  *pastix_data = NULL; /* Pointer to a storage structure needed by pastix           */
  pastix_int_t    iparm[IPARM_SIZE];  /* integer parameters for pastix                             */
  double          dparm[DPARM_SIZE];  /* floating parameters for pastix                            */
  pastix_int_t   *perm        = NULL; /* Permutation tabular                                       */
  pastix_int_t   *invp        = NULL; /* Reverse permutation tabular                               */
  int             ret, opt, islog = 0, check = 0;
  int             verbosemode = API_VERBOSE_NOT, nbthread = 1, transpose = API_NO;
  double          start= 0, end= 2;
  pastix_int_t    mat_type   = API_SYM_NO;
#ifndef FORCE_NOMPI
  int             required;           /* MPI thread level required                                 */
  int             provided;           /* MPI thread level provided                                 */
#endif
  int             mpid = 0 , mpisize = 1, packsize = -1, packed = 0, topack, nsol, cursol;
  int             nbrhs = 1;
  int nbpoints = 2;
  double norme1, norme2, step;
  char           *listoutputidx_filename=NULL;
  int            *listoutputidx=NULL;
  int            HOOKUP_CONSTRUCT=0;
  int            one_output =0;
  int            iterative = 0;
  const int iterend = 100;
  int countiter = iterend, nbrefact = 0;
  int charge, reste, mystart, myend, mystep;
  int max_authorized_iter = 5;
  struct timeval tv;
  double t0, t1, t2;
  double epsilon_ref=0.0;
  pastix_int_t ref_mode = API_REF_ONLY;       
  pastix_int_t ref_methode = API_RAF_GMRES; 
  /*******************************************/
  /*          MPI initialisation             */
  /*******************************************/
#ifndef FORCE_NOMPI
  required = MPI_THREAD_MULTIPLE;
  provided = -1;
  MPI_Init_thread(&argc, &argv, required, &provided);
  MPI_Comm_rank(MPI_COMM_WORLD, &mpid);
  MPI_Comm_size(MPI_COMM_WORLD, &mpisize);
  if (mpid == 0) {
    switch (provided) {
    case MPI_THREAD_SINGLE:
      printf("MPI_Init_thread level = MPI_THREAD_SINGLE\n");
      break;
    case MPI_THREAD_FUNNELED:
      printf("MPI_Init_thread level = MPI_THREAD_FUNNELED\n");
      break;
    case MPI_THREAD_SERIALIZED:
      printf("MPI_Init_thread level = MPI_THREAD_SERIALIZED\n");
      break;
    case MPI_THREAD_MULTIPLE:
      printf("MPI_Init_thread level = MPI_THREAD_MULTIPLE\n");
      break;
    default:
      printf("MPI_Init_thread level = ???\n");
    }
  }
#else
  mpid = 0;
#endif
  START_TIMER(t0);

  iparm[IPARM_REFINEMENT] = API_RAF_GMRES;
  /*******************************************/
  /*    Get options from command line        */
  /*******************************************/
  while ((opt = getopt(argc, argv, "s:e:lp:v:cytr:k:ho:ui:m:a:wdz")) != -1) {
    switch (opt) {
	case 'd':
	  debug = 1;
	  break;
    case 'z':
	  HOOKUP_CONSTRUCT = 1;
      break;	  
    case 'o':
      listoutputidx_filename = optarg;
      break;
    case 'k':
      packsize = atoi(optarg);
      break;
    case 's':
      start = atof(optarg);
      break;
    case 'e':
      end = atof(optarg);
      break;
    case 'l':
      islog = 1;
      break;
    case 'p':
      nbpoints = atoi(optarg);
      break;
    case 'v':
      verbosemode = atoi(optarg);
      break;
    case 't':
      transpose = API_YES;
      break;
    case 'r':
      nbthread = atoi(optarg);
      if (nbthread < 1) goto error;
      break;
    case 'c':
      check = 1;
      break;
    case 'y':
      mat_type = API_SYM_YES;
      type[1] = 'S';
      break;
    case 'x':
      mat_type = API_SYM_HER;
      type[1] = 'H';
      break;
    case 'u':
      one_output = 1;
      if (mpisize > 1) {
        fprintf(stderr, "uniq output only available without MPI");
        goto usage;
      }
      break;
    case 'i':
      iterative=1;
      epsilon_ref = atof(optarg);
      break;
    case 'm':
      max_authorized_iter=atoi(optarg);
      break;
    case 'a':
      switch (atoi(optarg)) {
      case 0:
        ref_methode = API_RAF_GMRES;
        break;
      case 1:
        ref_methode = API_RAF_GRAD;
        break;
      case 2:
        ref_methode = API_RAF_PIVOT;
        break;
      case 3:
        ref_methode = API_RAF_BICGSTAB;
        break;
      default:
        goto error;
      }
      ref_methode = API_RAF_GRAD;
      break;
    case 'w':
      ref_mode = API_REF_PREC;
      break;
    case 'h':
    default:
      goto usage;
    error:
      printf("unprocessed option -%c %s\n", opt, optarg);
    usage:
      printf("Computes (A + B * omega + C / omega) x = b, with omega in 2*PI*op(start), op = log10 is -l, identity otherwise.\n");
      printf("usage: %s [options] -- matrix1 matrix2 matrix3 rhs\n", argv[0]);
      printf("  options : -y             -- If matrix is symmetric\n");
      printf("            -x             -- If matrix is hermitian\n");
      printf("            -c             -- If check required\n");
      printf("            -t             -- If transpose solve\n");
      printf("            -l             -- Logarithmic step\n");
      printf("            -p <npoints>   -- Number pf points\n");
      printf("            -k <packsize>  -- number of solutions in a tar.gz pack\n");
      printf("            -s <double>    -- first frequency of the loop\n");
      printf("            -e <double>    -- last frequency of the loop\n");
      printf("            -v <verbosity> -- verbosity level\n");
      printf("            -r <threadNbr> -- Number of thread in PaStiX (IPARM_THREAD_NBR)\n");
      printf("            -o <filename>  -- binary file containing idx required in outputs\n");
      printf("            -u             -- gather all output in one file (only without MPI)\n");
      printf("            -i <precision> -- Activate iterative solve with given precision\n");
      printf("            -m <maxiter>   -- when -i is used, factorization is performed when\n"
             "                                more than maxiter iteration are required,\n"
             "                                2*maxiter are authorized.\n");
      printf("            -a <integer>   -- when -i is used, choose iterative method:\n");
      printf("                                0 - GMRES,\n");
      printf("                                1 = conjugate gradient,\n");
      printf("                                2 = simple iterative refinement,\n");
      printf("                                3 = bi-conjugate gradient stabilized\n");
      printf("            -w             -- when -i is used, the iterative refinement\n"
             "                                is performed with a preconditionner\n");
      printf("            -z             -- When matrix contrution is made by algotech binary\n");	  
      printf("            -h             -- Display this help\n");
      RETURN(COMMAND_LINE_ERROR);
    }
  }


  /*******************************************/
  /*      Read Matrice                       */
  /*******************************************/

  START_TIMER(t1);
  
  if (HOOKUP_CONSTRUCT==1)
  {
	if (0 != (ret = read_small_matrix(argv[optind],argv[optind + 1],argv[optind + 2], &incon, &n1, &n2, &n3, &colptr1, &colptr2, &colptr3, &rows1, &rows2, &rows3, &values1, &values2, &values3)))
    RETURN(ret);
	//printf("fin hook_u construct incon=%d",incon);
	if (0 != (ret = read_vector(argv[optind + 3], incon,n1, &rhs)))
    RETURN(ret);  
  } else {
		  if (0 != (ret = read_matrix(argv[optind], &n1, &colptr1, &rows1, &values1)))
			RETURN(ret);

		  if (0 != (ret = read_matrix(argv[optind + 1], &n2, &colptr2, &rows2, &values2)))
			RETURN(ret);

		  if (0 != (ret = read_matrix(argv[optind + 2], &n3, &colptr3, &rows3, &values3)))
			RETURN(ret);

		  if (0 != (ret = read_vector(argv[optind + 3], n1,n1, &rhs)))
			RETURN(ret);
		
  }
  //printf("fin hook_u construct n1=%d n2=%d n3=%d\n",n1,n2,n3);
  STOP_TIMER("Reading input matrices", t1);
  if (n1 != n2 || n1 != n3) RETURN(MATRIX_DIMENSIONS_ERROR);
  n = n1;
  if (listoutputidx_filename) {
    int tmp;
    /* Read list of output variable index required */
    FILE * f = fopen(listoutputidx_filename, "rb");
    if (f == NULL) {
      char error[1024];
      sprintf(error, "%s:%d:fopen %s", __FILE__, __LINE__, listoutputidx_filename);
      perror(error);
      return INPUTFILEREAD_ERROR;
    }
    if (1 != fread(&tmp, sizeof(pastix_int_t), 1, f)) {
      fprintf(stderr, "ERROR: reading %s : n\n", listoutputidx_filename);
      return INPUTFILEREAD_ERROR;
    }
    if (tmp < 0 || tmp > n) return INPUTFILEREAD_ERROR;

    if (NULL == (listoutputidx = malloc((tmp+1)*sizeof(pastix_int_t))))
      return MEMORY_ERROR;
    listoutputidx[0] = tmp;
    if (tmp != fread(listoutputidx+1, sizeof(pastix_int_t), tmp, f)) {
      fprintf(stderr, "ERROR: reading %s\n", listoutputidx_filename);
      free(listoutputidx);
      return MATRIX_READ_ERROR;
    }
    for (tmp = 1; tmp < listoutputidx[0]+1; tmp++) {
      if (listoutputidx[tmp] < 0 || listoutputidx[tmp] > n)
        return INPUTFILEREAD_ERROR;
    }
    fclose(f);
  }

  START_TIMER(t1);
  {
    pastix_int_t i, rowidx = 0;
    /* Build system matrix */
    if (NULL == (colptr = malloc((n+1)*sizeof(pastix_int_t))))
      RETURN(MEMORY_ERROR);
    for (i = 0; i < n; i++) {
      pastix_int_t rowidx1, rowidx2, rowidx3;
      colptr[i] = rowidx+1;
      rowidx1 = colptr1[i]-1;
      rowidx2 = colptr2[i]-1;
      rowidx3 = colptr3[i]-1;

      while(rowidx1 < colptr1[i+1] -1 ||
            rowidx2 < colptr2[i+1] -1 ||
            rowidx3 < colptr3[i+1] -1 ) {
        if (rowidx1 < colptr1[i+1] -1 &&
            rowidx2 < colptr2[i+1] -1 &&
            rowidx3 < colptr3[i+1] -1) {
          if (rows1[rowidx1] < rows2[rowidx2]) {
            if (rows1[rowidx1] < rows3[rowidx3]) {
              /* the first matrix as the smallest */
              rowidx1 ++;
            } else {
              /* the third one is the smaller, maybe with the first */
              if (rows1[rowidx1] == rows3[rowidx3]) {
                rowidx1++;
              }
              rowidx3++;
            }
          } else {
            if (rows2[rowidx2] < rows3[rowidx3]) {
              /* the second matrix as the smallest, maybe equal to first */
              if (rows1[rowidx1] == rows2[rowidx2]) {
                rowidx1++;
              }
              rowidx2 ++;
            } else {
              /* the third one is the smaller, maybe with the 2nd and first */
              if (rows1[rowidx1] == rows3[rowidx3]) {
                rowidx1++;
              }
              if (rows2[rowidx2] == rows3[rowidx3]) {
                rowidx2++;
              }
              rowidx3++;
            }
          }
        } else {
          if (!(rowidx1 < colptr1[i+1] -1)) {
            /* No more entries in 1*/
            if (!(rowidx2 < colptr2[i+1] -1)) {
              /* No more entries in 2 */
              rowidx3++;
            } else {
              if (!(rowidx3 < colptr3[i+1] -1)) {
                /* No more entries in 3 */
                rowidx2++;
              } else {
                increment_the_smallest_between_2(&rowidx2, rows2, &rowidx3, rows3, NULL);
              }
            }
          } else {
            /* There are entries in 1 */
            if (!(rowidx2 < colptr2[i+1] -1)) {
              /* No more entries in 2 */
              if (!(rowidx3 < colptr3[i+1] -1)) {
                rowidx1++;
              } else {
                increment_the_smallest_between_2(&rowidx1, rows1, &rowidx3, rows3, NULL);
              }
            } else {
              /* No more entries in 3 but in 2 */
              increment_the_smallest_between_2(&rowidx1, rows1, &rowidx2, rows2, NULL);
            }
          }
        }
        rowidx++;
      }
    }
    colptr[n] = rowidx+1;
    if (NULL == (rows = malloc((colptr[n]-1)*sizeof(pastix_int_t))))
      RETURN(MEMORY_ERROR);

    rowidx = 0;
    for (i = 0; i < n; i++) {
      pastix_int_t rowidx1, rowidx2, rowidx3;
      rowidx1 = colptr1[i]-1;
      rowidx2 = colptr2[i]-1;
      rowidx3 = colptr3[i]-1;
      while(rowidx1 < colptr1[i+1] -1 ||
            rowidx2 < colptr2[i+1] -1 ||
            rowidx3 < colptr3[i+1] -1 ) {
        if (DEBUG && (i < 10 || rowidx2 == 118))
          fprintf(stdout, "%d: %d %d %d -- %d %d %d %d %d %d\n", i,  rows1[rowidx1],  rows2[rowidx2],  rows3[rowidx3],
                  rowidx1, colptr1[i+1] -1, rowidx2, colptr2[i+1] -1, rowidx3, colptr3[i+1] -1);

        if (rowidx1 < colptr1[i+1] -1 &&
            rowidx2 < colptr2[i+1] -1 &&
            rowidx3 < colptr3[i+1] -1) {
          if (rows1[rowidx1] < rows2[rowidx2]) {
            if (rows1[rowidx1] < rows3[rowidx3]) {
              /* the first matrix as the smallest */
              rows[rowidx] = rows1[rowidx1];
              rowidx1 ++;
            } else {
              /* the third one is the smaller, maybe with the first */
              if (rows1[rowidx1] == rows3[rowidx3]) {
                rowidx1++;
              }
              rows[rowidx] = rows3[rowidx3];
              rowidx3++;

            }
          } else {
            if (rows2[rowidx2] < rows3[rowidx3]) {
              /* the second matrix as the smallest, maybe equal to first */
              if (DEBUG && (i < 10 || rowidx2 == 118)) fprintf(stdout, "set 2\n");
              if (rows1[rowidx1] == rows2[rowidx2]) {
                rowidx1++;
              }
              rows[rowidx] = rows2[rowidx2];
              rowidx2 ++;
            } else {
              /* the third one is the smaller, maybe with the 2nd and first */
              if (rows1[rowidx1] == rows3[rowidx3]) {
                rowidx1++;
              }
              if (rows2[rowidx2] == rows3[rowidx3]) {
                rowidx2++;
              }
              rows[rowidx] = rows3[rowidx3];
              rowidx3++;;

            }
          }
        } else {
          if (!(rowidx1 < colptr1[i+1] -1)) {
            /* No more entries in 1*/
            if (DEBUG && (i < 10 || rowidx2 == 118))
              fprintf(stdout, "1 est vide\n");
            if (!(rowidx2 < colptr2[i+1] -1)) {
              /* No more entries in 2 */
              rows[rowidx] = rows3[rowidx3];
              rowidx3++;
            } else {
              if (!(rowidx3 < colptr3[i+1] -1)) {
                /* No more entries in 3 */
                rows[rowidx] = rows2[rowidx2];
                rowidx2++;
              } else {
                increment_the_smallest_between_2(&rowidx2, rows2, &rowidx3, rows3, rows+rowidx);
              }
            }
          } else {
            /* There are entries in 1 */
            if (!(rowidx2 < colptr2[i+1] -1)) {
              /* No more entries in 2 */
              if (DEBUG && (i < 10 || rowidx2 == 118))
                fprintf(stdout, "No more entries in 2\n");
              if (!(rowidx3 < colptr3[i+1] -1)) {
                if (DEBUG && (i < 10 || rowidx2 == 118))
                  fprintf(stdout, "No more entries in 3\n");
                rows[rowidx] = rows1[rowidx1];
                rowidx1++;
              } else {
                increment_the_smallest_between_2(&rowidx1, rows1, &rowidx3, rows3, rows+rowidx);
              }
            } else {
              /* No more entries in 3 but in 2 */
              increment_the_smallest_between_2(&rowidx1, rows1, &rowidx2, rows2, rows+rowidx);
            }
          }
        }
        if (DEBUG && (i < 10 || rowidx2 == 118))
          fprintf(stdout, "%d %d %d %d\n", rows[rowidx],  rows1[rowidx1],  rows2[rowidx2],  rows3[rowidx3]);

        rowidx++;
      }
    }
  }
  if (NULL == (values = malloc((colptr[n]-1)*sizeof(double complex))))
    RETURN(MEMORY_ERROR);

  if (DEBUG) {
    d_cscd_save(n1, colptr1, rows1, values1, NULL, NULL, 1, "cscdm1", MPI_COMM_WORLD);
    d_cscd_save(n2, colptr2, rows2, values2, NULL, NULL, 1, "cscdm2", MPI_COMM_WORLD);
    d_cscd_save(n3, colptr3, rows3, values3, NULL, NULL, 1, "cscdm3", MPI_COMM_WORLD);
    z_cscd_save(n, colptr, rows, values, NULL, NULL, 1, "cscd", MPI_COMM_WORLD);
  }
  STOP_TIMER("Build main matrix", t1);

  /*******************************************/
  /*    Check Matrix format                  */
  /*******************************************/
  /*
   * Matrix needs :
   *    - to be in fortran numbering
   *    - to have only the lower triangular part in symmetric case
   *    - to have a graph with a symmetric structure in unsymmetric case
   */
  if (check == 1) {
    if (NO_ERR != z_pastix_checkMatrix(MPI_COMM_SELF, verbosemode,
                                       mat_type,
                                       API_YES,
                                       n, &colptr, &rows, NULL, NULL, 1)) {
      fprintf(stdout, "ERROR in pastix_checkMatrix\n");
      RETURN(MATRIX_CHECK_ERROR);
    }
  }

  if (islog) {
    start = log10(start);
    end = log10(end);
  }


  /*******************************************/
  /* Initialize parameters to default values */
  /*******************************************/
  iparm[IPARM_MODIFY_PARAMETER] = API_NO;
  z_pastix(&pastix_data, MPI_COMM_SELF,
           n, colptr, rows, NULL,
           perm, invp, NULL, 1, iparm, dparm);

  /*******************************************/
  /*       Customize some parameters         */
  /*******************************************/
  iparm[IPARM_THREAD_NBR] = nbthread;
  iparm[IPARM_SYM] = mat_type;
  switch (mat_type) {
  case API_SYM_YES:
    iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
    break;
  case API_SYM_HER:
    iparm[IPARM_FACTORIZATION] = API_FACT_LDLH;
    break;
  default:
    iparm[IPARM_FACTORIZATION] = API_FACT_LU;
  }
  iparm[IPARM_MATRIX_VERIFICATION] = API_NO;
  iparm[IPARM_VERBOSE]             = verbosemode;
  iparm[IPARM_RHS_MAKING]          = API_RHS_B;
  iparm[IPARM_START_TASK]          = API_TASK_ORDERING;

  iparm[IPARM_END_TASK]            = API_TASK_ANALYSE;
  iparm[IPARM_TRANSPOSE_SOLVE]     = transpose;
  if (iterative == 1) {
    if(iparm[IPARM_FACTORIZATION] != API_FACT_LU)
      iparm[IPARM_REFINEMENT]        = ref_methode;
    iparm[IPARM_GMRES_IM]            = 2*max_authorized_iter;
    iparm[IPARM_ITERMAX]             = 2*max_authorized_iter;
    dparm[DPARM_EPSILON_REFINEMENT]  = epsilon_ref;
  }
  /*******************************************/
  /*           Call pastix                   */
  /*******************************************/
  perm = malloc(n1*sizeof(pastix_int_t));
  invp = malloc(n1*sizeof(pastix_int_t));
  START_TIMER(t1);
  z_pastix(&pastix_data, MPI_COMM_SELF,
           n, colptr, rows, NULL,
           perm, invp, NULL, nbrhs, iparm, dparm);
  if (iparm[IPARM_ERROR_NUMBER] != NO_ERR)
    RETURN(PREPROCESSING_ERROR);
  STOP_TIMER("Analysis", t1);

  /* With multiple communicators we cannot use auto binding, we have to set the
   binding array */
  /* set thread binding, only works if number of threads*number of MPI process
   per node does not exceed number of cores */
  {
    int i, intra_node_rank = 0;
    pastix_int_t * bindtab;
    iparm[IPARM_BINDTHRD] = API_BIND_TAB;
    /* retrieve number of MPI process per node */
#ifndef FORCE_NOMPI
    {
      int i,len;
      char procname[MPI_MAX_PROCESSOR_NAME];
      int color, key;
      MPI_Comm intra_node_comm;

      MPI_Get_processor_name(procname,&len);
      MPI_Comm_rank(MPI_COMM_WORLD, &(key));
      color = 0;
      for (i = 0; i < len; i++)
        color = color*256*sizeof(char) + procname[i];
      MPI_Comm_split(MPI_COMM_WORLD, color, mpid, &intra_node_comm);
      MPI_Comm_rank(intra_node_comm, &intra_node_rank);
      MPI_Comm_free(&intra_node_comm);
    }
#endif
    bindtab = (pastix_int_t*)malloc(iparm[IPARM_THREAD_NBR]*sizeof(pastix_int_t));
    for (i = 0; i< iparm[IPARM_THREAD_NBR]; i++) {
      bindtab[i] = intra_node_rank*iparm[IPARM_THREAD_NBR]+i;
    }
    pastix_bindThreads(pastix_data, iparm[IPARM_THREAD_NBR], bindtab);
  }


  topack = 0;
  packed = 0;
  nsol = nbpoints;
  step = (end - start) / (double)(nbpoints-1);
  if (iterative == 1) {
    mystep = 1;
    charge = nbpoints/mpisize;
    reste  = nbpoints%mpisize;
    mystart = mpid*charge;
    if(mpid < reste) {
      charge++;
      mystart = mpid * (charge);
    } else {
      mystart = mpid * charge + reste;
    }
    myend = mystart + charge;
  } else {
    mystart = mpid;
    myend  = nbpoints;
    mystep = mpisize;
  }
  if (NULL == (sol = malloc(n*sizeof(double complex))))
    RETURN(MEMORY_ERROR);
  if (NULL == (solsaved = malloc(n*sizeof(double complex))))
    return MEMORY_ERROR;
  START_TIMER(t1);
  for ( cursol = mystart, freq = start + step * (double)mystart;
        cursol < myend;
        freq += step * (double)mystep, cursol += mystep ) {
    double omega = 2*M_PI*freq;
    if (islog) omega = 2*M_PI*pow(10,freq);

    /* copy RHS (double) into solution (double complex)*/
    {
      int j;
      for (j = 0; j < n; j++)
        sol[j] = rhs[j];
    }
    START_TIMER(t2);
    /* Fuse matrices */
    {
      pastix_int_t i, j, k, l, m;
      for (i = 0; i < n; i++) {
        m = colptr1[i]-1;
        k = colptr2[i]-1;
        l = colptr3[i]-1;
        for (j = colptr[i]-1; j < colptr[i+1]-1; j++) {
          values[j] = 0.;

          if( m < colptr1[i+1]-1 && rows[j] > rows1[m]) {
            fprintf(stdout, "rows[%d] %d > rows1[%d] %d && m %d < colptr1[i+1]-1 %d\n", j, rows[j], m, rows1[m], m, colptr1[i+1]-1);
            RETURN(MATRIX_SHAPE_ERROR);
          }
          if ( m < colptr1[i+1]-1 && rows[j] == rows1[m]) {
            values[j] += ((double complex)values1[m]);
            m++;
          }

          if(k < colptr2[i+1]-1 && rows[j] > rows2[k]) {
            fprintf(stdout, "rows[%d] %d > rows2[%d] %d && k %d < colptr2[i+1]-1 %d\n", j, rows[j], k, rows2[k], k, colptr2[i+1]-1);
            RETURN(MATRIX_SHAPE_ERROR);
          }
          if(k < colptr2[i+1]-1 &&  rows[j] == rows2[k]) {
            values[j] += I*((double complex)omega*values2[k]);
            k++;
          }
          if(l < colptr3[i+1]-1 && rows[j] > rows3[l]) {
            fprintf(stdout, "rows[%d] %d > rows3[%d] %d && l %d < colptr3[i+1]-1 %d\n", j, rows[j], l, rows3[l], l, colptr3[i+1]-1);
            RETURN(MATRIX_SHAPE_ERROR);
          }
          if (l < colptr3[i+1]-1 && rows[j] == rows3[l]) {
            values[j] += I*((double complex)values3[l]/omega);
            l++;
          }
        }
      }
    }

#ifdef MX	
  sprintf(name, "matrice_%d.mat", 1000);
  f = fopen(name, "wb");
  if (f == NULL) {
    return SOLUTION_WRITE_ERROR;
  }

  if (1 != fwrite(&n, sizeof(pastix_int_t), 1, f))
    return SOLUTION_WRITE_ERROR;
  if (n != fwrite(colptr, sizeof(pastix_int_t), n, f))
    return SOLUTION_WRITE_ERROR;
  if ((colptr[n-1]-1) != fwrite(rows, sizeof(pastix_int_t), (colptr[n-1]-1), f))
    return SOLUTION_WRITE_ERROR;
  if ((colptr[n-1]-1) != fwrite(values, sizeof(pastix_int_t), (colptr[n-1]-1), f))
    return SOLUTION_WRITE_ERROR;
  fclose(f);
#endif

    STOP_TIMER("Fuse matrices", t2);
    /*******************************************/
    /*    Check Matrix format                  */
    /*******************************************/
    /*
     * Matrix needs :
     *    - to be in fortran numbering
     *    - to have only the lower triangular part in symmetric case
     *    - to have a graph with a symmetric structure in unsymmetric case
     */
    if (check == 1) {
      if (NO_ERR != z_pastix_checkMatrix(MPI_COMM_SELF, verbosemode,
                                         mat_type,
                                         API_YES,
                                         n, &colptr, &rows, NULL, NULL, 1)) {
        fprintf(stdout, "ERROR in pastix_checkMatrix\n");
        RETURN(MATRIX_CHECK_ERROR);
      }
    }

    if (DEBUG) {
      char name[256];
      sprintf(name, "cscd_fuse_%g_%g_", ((islog)?(pow(10,freq)):freq), omega);
      z_cscd_save(n, colptr, rows, values, sol, NULL, 1, name, MPI_COMM_WORLD);
    }

   printf("frequence number %d : %g Hz \n", cursol+1, ((islog)?(pow(10,freq)):freq));
    if (iterative == 0 || countiter==iterend) {
      countiter=1;
      iparm[IPARM_REF_MODE]           = API_REF_FACT;
      iparm[IPARM_START_TASK]          = API_TASK_NUMFACT;
      iparm[IPARM_END_TASK]            = API_TASK_SOLVE;
      START_TIMER(t2);
      z_pastix(&pastix_data, MPI_COMM_SELF,
               n, colptr, rows, values,
               perm, invp, sol, nbrhs, iparm, dparm);
      STOP_TIMER("Fact and solve", t2);
      if (iparm[IPARM_ERROR_NUMBER] != NO_ERR)
        RETURN(FACTORSOLVE_ERROR);

      if (iterative == 1) {
        int j;
        for (j = 0; j < n; j++)
          solsaved[j] = sol[j];
      }
    } else {
      iparm[IPARM_REF_MODE]           = ref_mode;
      iparm[IPARM_START_TASK]          = API_TASK_NUMFACT;
      iparm[IPARM_END_TASK]            = API_TASK_SOLVE;
      START_TIMER(t2);
      z_pastix(&pastix_data, MPI_COMM_SELF,
               n, colptr, rows, values,
               perm, invp, solsaved, nbrhs, iparm, dparm);
      STOP_TIMER("Set A and X0", t2);

      iparm[IPARM_START_TASK]          = API_TASK_REFINE;
      iparm[IPARM_END_TASK]            = API_TASK_REFINE;

      START_TIMER(t2);
      z_pastix(&pastix_data, MPI_COMM_SELF,
               n, colptr, rows, values,
               perm, invp, sol, nbrhs, iparm, dparm);
      STOP_TIMER("Iterative solve", t2);
      if (iparm[IPARM_ERROR_NUMBER] != NO_ERR)
        RETURN(FACTORSOLVE_ERROR);

      countiter++;
      /* factorize in next iteration if we have done more than max_authorized_iter iterations */
      if(iparm[IPARM_NBITER] >= max_authorized_iter) {
        countiter = iterend;
        nbrefact+=1;
      }

      /* if we did not converge perform a direct solve with current linear system */
      if(dparm[DPARM_RELATIVE_ERROR] > dparm[DPARM_EPSILON_REFINEMENT]) {
        int j;
        printf("relative error : %g \n", dparm[DPARM_RELATIVE_ERROR]);
        for (j = 0; j < n; j++)
          sol[j] = rhs[j];

        countiter=1;
        iparm[IPARM_REF_MODE]           = API_REF_FACT;
        iparm[IPARM_START_TASK]          = API_TASK_NUMFACT;
        iparm[IPARM_END_TASK]            = API_TASK_SOLVE;

        START_TIMER(t2);
        z_pastix(&pastix_data, MPI_COMM_SELF,
                 n, colptr, rows, values,
                 perm, invp, sol, nbrhs, iparm, dparm);
        STOP_TIMER("Iterative solve (again)", t2);
        if (iparm[IPARM_ERROR_NUMBER] != NO_ERR)
          RETURN(FACTORSOLVE_ERROR);
      }
      {
        int j;
        for (j = 0; j < n; j++)
          solsaved[j] = sol[j];
      }
    }

    START_TIMER(t2);
    if (one_output) {
      if (0 != (ret = save_vector_uniq(n, sol, listoutputidx, ((cursol == nbpoints-1)?1:0))))
        RETURN(ret);
    } else {
      if (0 != (ret = save_vector(n, sol, listoutputidx, cursol)))
        RETURN(ret);
    }

    topack += MIN(mpisize, nsol - (cursol - mpid));

    if (packsize > 0 && topack >= packsize && packed < nsol) {
#ifndef FORCE_NOMPI
      MPI_Barrier(MPI_COMM_WORLD);
#endif
      while (topack >= packsize && packed < nsol) {
        if (mpid == 0) {
          int i;
          char * cmd;
          cmd = malloc((packsize*15+26+60)*sizeof(char));
          sprintf(cmd, "tar -cvzf sol_%d.tar.gz", packed+packsize);
          for (i = 0; i < packsize; i++) {
            char file[15], file_saved[20];
            sprintf(file, "sol_%d.mat", ++packed);
            sprintf(file_saved, "%s.saved", file);
            while (access( file_saved, F_OK ) == -1) {
              usleep(50);
            }
            sprintf(cmd, "%s %s", cmd, file);
            topack--;
          }
          sprintf(cmd, "%s > sol_%d.tar.gz.out 2>&1 && touch sol_%d.tar.gz.saved", cmd, packed, packed);
          fprintf(stdout, "cmd : %s\n", cmd);
          system(cmd);
          free(cmd);
        } else {
          packed += packsize;
          topack -= packsize;
        }
      }
    }
    if (check) {
      /* check the solution */
      int CS_ii,CS_jj;
      ax = malloc(n*sizeof(double complex));
      memset(ax, 0, n*sizeof(double complex));
      if (iparm[IPARM_TRANSPOSE_SOLVE] == API_NO) {
        for (CS_ii= 0; CS_ii < n; CS_ii++) {
          for (CS_jj = colptr[CS_ii]-1;
               CS_jj < colptr[CS_ii+1] - 1;
               CS_jj++) {
            ax[rows[CS_jj]-1] += values[CS_jj]*sol[CS_ii];
            if ((MTX_ISSYM(type) == 1) &&
                (CS_ii != (rows[CS_jj]-1))) {
              ax[CS_ii] += values[CS_jj]*sol[rows[CS_jj]-1];
            }
            if ((MTX_ISHER(type) == 1) &&
                (CS_ii != (rows[CS_jj]-1))) {
              ax[CS_ii] = ax[CS_ii] +
                CONJ(values[CS_jj])*sol[rows[CS_jj]-1];
            }
          }
        }
      } else {
        for (CS_ii= 0; CS_ii < n; CS_ii++) {
          for (CS_jj = colptr[CS_ii]-1;
               CS_jj < colptr[CS_ii+1] - 1;
               CS_jj++) {
            ax[CS_ii] += values[CS_jj]*sol[rows[CS_jj]-1];
            if ((MTX_ISSYM(type) == 1) &&
                (CS_ii != (rows[CS_jj]-1))) {
              ax[rows[CS_jj]-1] = ax[rows[CS_jj]-1] +
                values[CS_jj]*sol[CS_ii];
            }
            if ((MTX_ISHER(type) == 1) &&
                (CS_ii != (rows[CS_jj]-1))) {
              ax[rows[CS_jj]-1] = ax[rows[CS_jj]-1] +
                CONJ(values[CS_jj])*sol[rows[CS_jj]-1];
            }
          }
        }
      }
      norme1= norme2 = 0;
      for (CS_ii= 0; CS_ii < n; CS_ii++) {
        norme1 += (double)((ax[CS_ii] - rhs[CS_ii])*CONJ(ax[CS_ii] - rhs[CS_ii]));
        norme2 += (double)(rhs[CS_ii] * CONJ(rhs[CS_ii]));
      }
      if (mpid == 0)
        fprintf(stdout, "Precision : ||ax -b||/||b|| = %.20lg\n",
                sqrt(norme1/norme2));
      free(ax);
    }
    STOP_TIMER("Save (and pack ?)", t2);

  }

  STOP_TIMER("Loop on frequencies)", t1);
  if (packsize > 0) {
    while (nsol > packed) {
      int nbpack ;
      if ((nsol - packed) > packsize)
        nbpack = packsize;
      else
        nbpack = nsol%packsize;
#ifndef FORCE_NOMPI
      MPI_Barrier(MPI_COMM_WORLD);
#endif
      if (mpid == 0) {
        int i;
        char * cmd;
        cmd = malloc((nbpack*15+26+60)*sizeof(char));
        sprintf(cmd, "tar -cvzf sol_%d.tar.gz", packed+packsize);
        for (i = 0; i < nbpack; i++) {
          char file[15], file_saved[20];
          sprintf(file, "sol_%d.mat", ++packed);
          sprintf(file_saved, "%s.saved", file);
          while (access( file_saved, F_OK ) == -1) {
            usleep(50);
          }
          sprintf(cmd, "%s %s", cmd, file);
        }
        sprintf(cmd, "%s  > sol_%d.tar.gz.out 2>&1 && touch sol_%d.tar.gz.saved", cmd, packed-nbpack+packsize, packed-nbpack+packsize);
        fprintf(stdout, "cmd : %s\n", cmd);
        system(cmd);
        free(cmd);
      } else {
        packed += nbpack;
      }
    }
  }

  iparm[IPARM_START_TASK]          = API_TASK_CLEAN;
  iparm[IPARM_END_TASK]            = API_TASK_CLEAN;
  z_pastix(&pastix_data, MPI_COMM_SELF,
           n1, colptr1, rows1, NULL,
           perm, invp, NULL, nbrhs, iparm, dparm);
  free(perm);
  free(invp);
  free(colptr);
  free(colptr1);
  free(colptr2);
  free(colptr3);
  free(values);
  free(values1);
  free(values2);
  free(values3);
  free(rhs);
  free(sol);
  free(solsaved);
  free(rows);
  free(rows1);
  free(rows2);
  free(rows3);  
  STOP_TIMER("Total)", t0);
  if (iterative == 1) {
    printf("nb refactorization = %d \n",nbrefact);
  }
#ifndef FORCE_NOMPI
  MPI_Finalize();
#endif

  RETURN(EXIT_SUCCESS);
}
